blob: 995b7ba683fc33bf702821c6afdd8e1af3aafc71 [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>
30#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
38namespace android {
39namespace vold {
40
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070041namespace {
42const std::string kMetadataCPFile = "/metadata/vold/checkpoint";
43
44bool setBowState(std::string const& block_device, std::string const& state) {
45 if (block_device.substr(0, 5) != "/dev/") {
46 LOG(ERROR) << "Expected block device, got " << block_device;
47 return false;
48 }
49
50 std::string state_filename = std::string("/sys/") + block_device.substr(5) + "/bow/state";
51 if (!android::base::WriteStringToFile(state, state_filename)) {
52 PLOG(ERROR) << "Failed to write to file " << state_filename;
53 return false;
54 }
55
56 return true;
57}
58
59} // namespace
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070060
61bool cp_startCheckpoint(int retry) {
62 if (retry < -1) return false;
63 std::string content = std::to_string(retry);
64 return android::base::WriteStringToFile(content, kMetadataCPFile);
65}
66
67bool cp_commitChanges() {
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070068 // Must take action for list of mounted checkpointed things here
69 // To do this, we walk the list of mounted file systems.
70 // But we also need to get the matching fstab entries to see
71 // the original flags
Paul Lawrence20400892018-10-03 14:14:52 -070072 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 false;
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070075
Paul Lawrence20400892018-10-03 14:14:52 -070076 auto mounts = std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>{
77 fs_mgr_read_fstab("/proc/mounts"), fs_mgr_free_fstab};
78 if (!mounts) return false;
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070079
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070080 // Walk mounted file systems
81 for (int i = 0; i < mounts->num_entries; ++i) {
82 const fstab_rec* mount_rec = &mounts->recs[i];
Paul Lawrence20400892018-10-03 14:14:52 -070083 const fstab_rec* fstab_rec =
84 fs_mgr_get_entry_for_mount_point(fstab_default.get(), mount_rec->mount_point);
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070085 if (!fstab_rec) continue;
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070086
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070087 if (fs_mgr_is_checkpoint_fs(fstab_rec)) {
88 if (!strcmp(fstab_rec->fs_type, "f2fs")) {
89 mount(mount_rec->blk_device, mount_rec->mount_point, "none",
90 MS_REMOUNT | fstab_rec->flags, "checkpoint=enable");
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070091 }
Paul Lawrence1abb2fe2018-09-21 10:49:57 -070092 } else if (fs_mgr_is_checkpoint_blk(fstab_rec)) {
93 setBowState(mount_rec->blk_device, "2");
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070094 }
95 }
Daniel Rosenberg65f99c92018-08-28 01:58:49 -070096 return android::base::RemoveFileIfExists(kMetadataCPFile);
97}
98
99void cp_abortChanges() {
100 android_reboot(ANDROID_RB_RESTART2, 0, nullptr);
101}
102
103bool cp_needRollback(const std::string& id) {
104 std::string content;
105 bool ret;
106
107 ret = android::base::ReadFileToString(kMetadataCPFile, &content);
108 if (ret) return content == "0";
109 return false;
110}
111
112bool cp_needsCheckpoint(void) {
113 bool ret;
114 std::string content;
115
116 ret = android::base::ReadFileToString(kMetadataCPFile, &content);
117 if (ret) return content != "0";
118 return false;
119}
120
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700121bool cp_prepareDriveForCheckpoint(const std::string&) {
Paul Lawrence20400892018-10-03 14:14:52 -0700122 auto fstab_default = std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>{
123 fs_mgr_read_fstab_default(), fs_mgr_free_fstab};
124 if (!fstab_default) return false;
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700125
Paul Lawrence20400892018-10-03 14:14:52 -0700126 auto mounts = std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>{
127 fs_mgr_read_fstab("/proc/mounts"), fs_mgr_free_fstab};
128 if (!mounts) return false;
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700129
130 for (int i = 0; i < mounts->num_entries; ++i) {
131 const fstab_rec* mount_rec = &mounts->recs[i];
Paul Lawrence20400892018-10-03 14:14:52 -0700132 const fstab_rec* fstab_rec =
133 fs_mgr_get_entry_for_mount_point(fstab_default.get(), mount_rec->mount_point);
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700134 if (!fstab_rec) continue;
135
136 if (fs_mgr_is_checkpoint_blk(fstab_rec)) {
137 android::base::unique_fd fd(
138 TEMP_FAILURE_RETRY(open(mount_rec->mount_point, O_RDONLY | O_CLOEXEC)));
139 if (!fd) {
140 PLOG(ERROR) << "Failed to open mount point" << mount_rec->mount_point;
141 continue;
142 }
143
144 struct fstrim_range range = {};
145 range.len = ULLONG_MAX;
146 if (ioctl(fd, FITRIM, &range)) {
147 PLOG(ERROR) << "Failed to trim " << mount_rec->mount_point;
148 continue;
149 }
150
151 setBowState(mount_rec->blk_device, "1");
152 }
153 }
Paul Lawrence1abb2fe2018-09-21 10:49:57 -0700154 return true;
155}
156
157namespace {
158const int kBlockSize = 4096;
159const int kSectorSize = 512;
160
161typedef uint64_t sector_t;
162
163struct log_entry {
164 sector_t source;
165 sector_t dest;
166 uint32_t size;
167 uint32_t checksum;
168} __attribute__((packed));
169
170struct log_sector {
171 uint32_t magic;
172 uint32_t count;
173 uint32_t sequence;
174 struct log_entry entries[];
175} __attribute__((packed));
176
177// MAGIC is BOW in ascii
178const int kMagic = 0x00574f42;
179
180void crc32(const void* data, size_t n_bytes, uint32_t* crc) {
181 static uint32_t table[0x100] = {
182 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
183 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
184 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
185 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
186 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
187 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
188 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
189 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
190 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
191 0xB6662D3D,
192
193 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5,
194 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
195 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED,
196 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
197 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074,
198 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC,
199 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C,
200 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
201 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B,
202 0xC0BA6CAD,
203
204 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
205 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D,
206 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D,
207 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
208 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4,
209 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C,
210 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C,
211 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
212 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B,
213 0x5BDEAE1D,
214
215 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785,
216 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D,
217 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD,
218 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
219 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354,
220 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
221 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C,
222 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
223 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B,
224 0x2D02EF8D};
225
226 for (size_t i = 0; i < n_bytes; ++i) {
227 *crc ^= ((uint8_t*)data)[i];
228 *crc = table[(uint8_t)*crc] ^ *crc >> 8;
229 }
230}
231
232} // namespace
233
234bool cp_restoreCheckpoint(const std::string& blockDevice) {
235 LOG(ERROR) << "Restoring checkpoint on " << blockDevice;
236 std::fstream device(blockDevice, std::ios::binary | std::ios::in | std::ios::out);
237 if (!device) {
238 PLOG(ERROR) << "Cannot open " << blockDevice;
239 return false;
240 }
241 char buffer[kBlockSize];
242 device.read(buffer, kBlockSize);
243 log_sector& ls = *(log_sector*)buffer;
244 if (ls.magic != kMagic) {
245 LOG(ERROR) << "No magic";
246 return false;
247 }
248
249 LOG(INFO) << "Restoring " << ls.sequence << " log sectors";
250
251 for (int sequence = ls.sequence; sequence >= 0; sequence--) {
252 char buffer[kBlockSize];
253 device.seekg(0);
254 device.read(buffer, kBlockSize);
255 log_sector& ls = *(log_sector*)buffer;
256 if (ls.magic != kMagic) {
257 LOG(ERROR) << "No magic!";
258 return false;
259 }
260
261 if ((int)ls.sequence != sequence) {
262 LOG(ERROR) << "Expecting log sector " << sequence << " but got " << ls.sequence;
263 return false;
264 }
265
266 LOG(INFO) << "Restoring from log sector " << ls.sequence;
267
268 for (log_entry* le = &ls.entries[ls.count - 1]; le >= ls.entries; --le) {
269 LOG(INFO) << "Restoring " << le->size << " bytes from sector " << le->dest << " to "
270 << le->source << " with checksum " << std::hex << le->checksum;
271 std::vector<char> buffer(le->size);
272 device.seekg(le->dest * kSectorSize);
273 device.read(&buffer[0], le->size);
274
275 uint32_t checksum = le->source / (kBlockSize / kSectorSize);
276 for (size_t i = 0; i < le->size; i += kBlockSize) {
277 crc32(&buffer[i], kBlockSize, &checksum);
278 }
279
280 if (le->checksum && checksum != le->checksum) {
281 LOG(ERROR) << "Checksums don't match " << std::hex << checksum;
282 return false;
283 }
284
285 device.seekg(le->source * kSectorSize);
286 device.write(&buffer[0], le->size);
287 }
288 }
289
290 return true;
Daniel Rosenberg65f99c92018-08-28 01:58:49 -0700291}
292
293bool cp_markBootAttempt() {
294 std::string oldContent, newContent;
295 int retry = 0;
296 if (!android::base::ReadFileToString(kMetadataCPFile, &oldContent)) return false;
297
298 if (!android::base::ParseInt(oldContent, &retry)) return false;
299 if (retry > 0) retry--;
300
301 newContent = std::to_string(retry);
302 return android::base::WriteStringToFile(newContent, kMetadataCPFile);
303}
304
305} // namespace vold
306} // namespace android