EncryptInplace.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. /*
  2. * Copyright (C) 2016 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. #include "EncryptInplace.h"
  17. #include <ext4_utils/ext4.h>
  18. #include <ext4_utils/ext4_utils.h>
  19. #include <f2fs_sparseblock.h>
  20. #include <fcntl.h>
  21. #include <inttypes.h>
  22. #include <stdint.h>
  23. #include <stdio.h>
  24. #include <sys/stat.h>
  25. #include <sys/types.h>
  26. #include <time.h>
  27. #include <algorithm>
  28. #include <android-base/logging.h>
  29. #include <android-base/properties.h>
  30. // HORRIBLE HACK, FIXME
  31. #include "cryptfs.h"
  32. // FIXME horrible cut-and-paste code
  33. static inline int unix_read(int fd, void* buff, int len) {
  34. return TEMP_FAILURE_RETRY(read(fd, buff, len));
  35. }
  36. static inline int unix_write(int fd, const void* buff, int len) {
  37. return TEMP_FAILURE_RETRY(write(fd, buff, len));
  38. }
  39. #define CRYPT_SECTORS_PER_BUFSIZE (CRYPT_INPLACE_BUFSIZE / CRYPT_SECTOR_SIZE)
  40. /* aligned 32K writes tends to make flash happy.
  41. * SD card association recommends it.
  42. */
  43. #ifndef CONFIG_HW_DISK_ENCRYPTION
  44. #define BLOCKS_AT_A_TIME 8
  45. #else
  46. #define BLOCKS_AT_A_TIME 1024
  47. #endif
  48. struct encryptGroupsData {
  49. int realfd;
  50. int cryptofd;
  51. off64_t numblocks;
  52. off64_t one_pct, cur_pct, new_pct;
  53. off64_t blocks_already_done, tot_numblocks;
  54. off64_t used_blocks_already_done, tot_used_blocks;
  55. const char* real_blkdev;
  56. const char* crypto_blkdev;
  57. int count;
  58. off64_t offset;
  59. char* buffer;
  60. off64_t last_written_sector;
  61. int completed;
  62. time_t time_started;
  63. int remaining_time;
  64. bool set_progress_properties;
  65. };
  66. static void update_progress(struct encryptGroupsData* data, int is_used) {
  67. data->blocks_already_done++;
  68. if (is_used) {
  69. data->used_blocks_already_done++;
  70. }
  71. if (data->tot_used_blocks) {
  72. data->new_pct = data->used_blocks_already_done / data->one_pct;
  73. } else {
  74. data->new_pct = data->blocks_already_done / data->one_pct;
  75. }
  76. if (!data->set_progress_properties) return;
  77. if (data->new_pct > data->cur_pct) {
  78. char buf[8];
  79. data->cur_pct = data->new_pct;
  80. snprintf(buf, sizeof(buf), "%" PRId64, data->cur_pct);
  81. android::base::SetProperty("vold.encrypt_progress", buf);
  82. }
  83. if (data->cur_pct >= 5) {
  84. struct timespec time_now;
  85. if (clock_gettime(CLOCK_MONOTONIC, &time_now)) {
  86. LOG(WARNING) << "Error getting time";
  87. } else {
  88. double elapsed_time = difftime(time_now.tv_sec, data->time_started);
  89. off64_t remaining_blocks = data->tot_used_blocks - data->used_blocks_already_done;
  90. int remaining_time =
  91. (int)(elapsed_time * remaining_blocks / data->used_blocks_already_done);
  92. // Change time only if not yet set, lower, or a lot higher for
  93. // best user experience
  94. if (data->remaining_time == -1 || remaining_time < data->remaining_time ||
  95. remaining_time > data->remaining_time + 60) {
  96. char buf[8];
  97. snprintf(buf, sizeof(buf), "%d", remaining_time);
  98. android::base::SetProperty("vold.encrypt_time_remaining", buf);
  99. data->remaining_time = remaining_time;
  100. }
  101. }
  102. }
  103. }
  104. static void log_progress(struct encryptGroupsData const* data, bool completed) {
  105. // Precondition - if completed data = 0 else data != 0
  106. // Track progress so we can skip logging blocks
  107. static off64_t offset = -1;
  108. // Need to close existing 'Encrypting from' log?
  109. if (completed || (offset != -1 && data->offset != offset)) {
  110. LOG(INFO) << "Encrypted to sector " << offset / info.block_size * CRYPT_SECTOR_SIZE;
  111. offset = -1;
  112. }
  113. // Need to start new 'Encrypting from' log?
  114. if (!completed && offset != data->offset) {
  115. LOG(INFO) << "Encrypting from sector " << data->offset / info.block_size * CRYPT_SECTOR_SIZE;
  116. }
  117. // Update offset
  118. if (!completed) {
  119. offset = data->offset + (off64_t)data->count * info.block_size;
  120. }
  121. }
  122. static int flush_outstanding_data(struct encryptGroupsData* data) {
  123. if (data->count == 0) {
  124. return 0;
  125. }
  126. LOG(DEBUG) << "Copying " << data->count << " blocks at offset " << data->offset;
  127. if (pread64(data->realfd, data->buffer, info.block_size * data->count, data->offset) <= 0) {
  128. LOG(ERROR) << "Error reading real_blkdev " << data->real_blkdev << " for inplace encrypt";
  129. return -1;
  130. }
  131. if (pwrite64(data->cryptofd, data->buffer, info.block_size * data->count, data->offset) <= 0) {
  132. LOG(ERROR) << "Error writing crypto_blkdev " << data->crypto_blkdev
  133. << " for inplace encrypt";
  134. return -1;
  135. } else {
  136. log_progress(data, false);
  137. }
  138. data->count = 0;
  139. data->last_written_sector =
  140. (data->offset + data->count) / info.block_size * CRYPT_SECTOR_SIZE - 1;
  141. return 0;
  142. }
  143. static int encrypt_groups(struct encryptGroupsData* data) {
  144. unsigned int i;
  145. u8* block_bitmap = 0;
  146. unsigned int block;
  147. off64_t ret;
  148. int rc = -1;
  149. data->buffer = (char*)malloc(info.block_size * BLOCKS_AT_A_TIME);
  150. if (!data->buffer) {
  151. LOG(ERROR) << "Failed to allocate crypto buffer";
  152. goto errout;
  153. }
  154. block_bitmap = (u8*)malloc(info.block_size);
  155. if (!block_bitmap) {
  156. LOG(ERROR) << "failed to allocate block bitmap";
  157. goto errout;
  158. }
  159. for (i = 0; i < aux_info.groups; ++i) {
  160. LOG(INFO) << "Encrypting group " << i;
  161. u32 first_block = aux_info.first_data_block + i * info.blocks_per_group;
  162. u32 block_count = std::min(info.blocks_per_group, (u32)(aux_info.len_blocks - first_block));
  163. off64_t offset = (u64)info.block_size * aux_info.bg_desc[i].bg_block_bitmap;
  164. ret = pread64(data->realfd, block_bitmap, info.block_size, offset);
  165. if (ret != (int)info.block_size) {
  166. LOG(ERROR) << "failed to read all of block group bitmap " << i;
  167. goto errout;
  168. }
  169. offset = (u64)info.block_size * first_block;
  170. data->count = 0;
  171. for (block = 0; block < block_count; block++) {
  172. int used = (aux_info.bg_desc[i].bg_flags & EXT4_BG_BLOCK_UNINIT)
  173. ? 0
  174. : bitmap_get_bit(block_bitmap, block);
  175. update_progress(data, used);
  176. if (used) {
  177. if (data->count == 0) {
  178. data->offset = offset;
  179. }
  180. data->count++;
  181. } else {
  182. if (flush_outstanding_data(data)) {
  183. goto errout;
  184. }
  185. }
  186. offset += info.block_size;
  187. /* Write data if we are aligned or buffer size reached */
  188. if (offset % (info.block_size * BLOCKS_AT_A_TIME) == 0 ||
  189. data->count == BLOCKS_AT_A_TIME) {
  190. if (flush_outstanding_data(data)) {
  191. goto errout;
  192. }
  193. }
  194. }
  195. if (flush_outstanding_data(data)) {
  196. goto errout;
  197. }
  198. }
  199. data->completed = 1;
  200. rc = 0;
  201. errout:
  202. log_progress(0, true);
  203. free(data->buffer);
  204. free(block_bitmap);
  205. return rc;
  206. }
  207. static int cryptfs_enable_inplace_ext4(const char* crypto_blkdev, const char* real_blkdev,
  208. off64_t size, off64_t* size_already_done, off64_t tot_size,
  209. off64_t previously_encrypted_upto,
  210. bool set_progress_properties) {
  211. u32 i;
  212. struct encryptGroupsData data;
  213. int rc; // Can't initialize without causing warning -Wclobbered
  214. int retries = RETRY_MOUNT_ATTEMPTS;
  215. struct timespec time_started = {0};
  216. if (previously_encrypted_upto > *size_already_done) {
  217. LOG(DEBUG) << "Not fast encrypting since resuming part way through";
  218. return -1;
  219. }
  220. memset(&data, 0, sizeof(data));
  221. data.real_blkdev = real_blkdev;
  222. data.crypto_blkdev = crypto_blkdev;
  223. data.set_progress_properties = set_progress_properties;
  224. LOG(DEBUG) << "Opening" << real_blkdev;
  225. if ((data.realfd = open(real_blkdev, O_RDWR | O_CLOEXEC)) < 0) {
  226. PLOG(ERROR) << "Error opening real_blkdev " << real_blkdev << " for inplace encrypt";
  227. rc = -1;
  228. goto errout;
  229. }
  230. LOG(DEBUG) << "Opening" << crypto_blkdev;
  231. // Wait until the block device appears. Re-use the mount retry values since it is reasonable.
  232. while ((data.cryptofd = open(crypto_blkdev, O_WRONLY | O_CLOEXEC)) < 0) {
  233. if (--retries) {
  234. PLOG(ERROR) << "Error opening crypto_blkdev " << crypto_blkdev
  235. << " for ext4 inplace encrypt, retrying";
  236. sleep(RETRY_MOUNT_DELAY_SECONDS);
  237. } else {
  238. PLOG(ERROR) << "Error opening crypto_blkdev " << crypto_blkdev
  239. << " for ext4 inplace encrypt";
  240. rc = ENABLE_INPLACE_ERR_DEV;
  241. goto errout;
  242. }
  243. }
  244. if (setjmp(setjmp_env)) { // NOLINT
  245. LOG(ERROR) << "Reading ext4 extent caused an exception";
  246. rc = -1;
  247. goto errout;
  248. }
  249. if (read_ext(data.realfd, 0) != 0) {
  250. LOG(ERROR) << "Failed to read ext4 extent";
  251. rc = -1;
  252. goto errout;
  253. }
  254. data.numblocks = size / CRYPT_SECTORS_PER_BUFSIZE;
  255. data.tot_numblocks = tot_size / CRYPT_SECTORS_PER_BUFSIZE;
  256. data.blocks_already_done = *size_already_done / CRYPT_SECTORS_PER_BUFSIZE;
  257. LOG(INFO) << "Encrypting ext4 filesystem in place...";
  258. data.tot_used_blocks = data.numblocks;
  259. for (i = 0; i < aux_info.groups; ++i) {
  260. data.tot_used_blocks -= aux_info.bg_desc[i].bg_free_blocks_count;
  261. }
  262. data.one_pct = data.tot_used_blocks / 100;
  263. data.cur_pct = 0;
  264. if (clock_gettime(CLOCK_MONOTONIC, &time_started)) {
  265. LOG(WARNING) << "Error getting time at start";
  266. // Note - continue anyway - we'll run with 0
  267. }
  268. data.time_started = time_started.tv_sec;
  269. data.remaining_time = -1;
  270. rc = encrypt_groups(&data);
  271. if (rc) {
  272. LOG(ERROR) << "Error encrypting groups";
  273. goto errout;
  274. }
  275. *size_already_done += data.completed ? size : data.last_written_sector;
  276. rc = 0;
  277. errout:
  278. close(data.realfd);
  279. close(data.cryptofd);
  280. return rc;
  281. }
  282. static void log_progress_f2fs(u64 block, bool completed) {
  283. // Precondition - if completed data = 0 else data != 0
  284. // Track progress so we can skip logging blocks
  285. static u64 last_block = (u64)-1;
  286. // Need to close existing 'Encrypting from' log?
  287. if (completed || (last_block != (u64)-1 && block != last_block + 1)) {
  288. LOG(INFO) << "Encrypted to block " << last_block;
  289. last_block = -1;
  290. }
  291. // Need to start new 'Encrypting from' log?
  292. if (!completed && (last_block == (u64)-1 || block != last_block + 1)) {
  293. LOG(INFO) << "Encrypting from block " << block;
  294. }
  295. // Update offset
  296. if (!completed) {
  297. last_block = block;
  298. }
  299. }
  300. static int encrypt_one_block_f2fs(u64 pos, void* data) {
  301. struct encryptGroupsData* priv_dat = (struct encryptGroupsData*)data;
  302. priv_dat->blocks_already_done = pos - 1;
  303. update_progress(priv_dat, 1);
  304. off64_t offset = pos * CRYPT_INPLACE_BUFSIZE;
  305. if (pread64(priv_dat->realfd, priv_dat->buffer, CRYPT_INPLACE_BUFSIZE, offset) <= 0) {
  306. LOG(ERROR) << "Error reading real_blkdev " << priv_dat->crypto_blkdev
  307. << " for f2fs inplace encrypt";
  308. return -1;
  309. }
  310. if (pwrite64(priv_dat->cryptofd, priv_dat->buffer, CRYPT_INPLACE_BUFSIZE, offset) <= 0) {
  311. LOG(ERROR) << "Error writing crypto_blkdev " << priv_dat->crypto_blkdev
  312. << " for f2fs inplace encrypt";
  313. return -1;
  314. } else {
  315. log_progress_f2fs(pos, false);
  316. }
  317. return 0;
  318. }
  319. static int cryptfs_enable_inplace_f2fs(const char* crypto_blkdev, const char* real_blkdev,
  320. off64_t size, off64_t* size_already_done, off64_t tot_size,
  321. off64_t previously_encrypted_upto,
  322. bool set_progress_properties) {
  323. struct encryptGroupsData data;
  324. struct f2fs_info* f2fs_info = NULL;
  325. int rc = ENABLE_INPLACE_ERR_OTHER;
  326. if (previously_encrypted_upto > *size_already_done) {
  327. LOG(DEBUG) << "Not fast encrypting since resuming part way through";
  328. return ENABLE_INPLACE_ERR_OTHER;
  329. }
  330. memset(&data, 0, sizeof(data));
  331. data.real_blkdev = real_blkdev;
  332. data.crypto_blkdev = crypto_blkdev;
  333. data.set_progress_properties = set_progress_properties;
  334. data.realfd = -1;
  335. data.cryptofd = -1;
  336. if ((data.realfd = open64(real_blkdev, O_RDWR | O_CLOEXEC)) < 0) {
  337. PLOG(ERROR) << "Error opening real_blkdev " << real_blkdev << " for f2fs inplace encrypt";
  338. goto errout;
  339. }
  340. if ((data.cryptofd = open64(crypto_blkdev, O_WRONLY | O_CLOEXEC)) < 0) {
  341. PLOG(ERROR) << "Error opening crypto_blkdev " << crypto_blkdev
  342. << " for f2fs inplace encrypt";
  343. rc = ENABLE_INPLACE_ERR_DEV;
  344. goto errout;
  345. }
  346. f2fs_info = generate_f2fs_info(data.realfd);
  347. if (!f2fs_info) goto errout;
  348. data.numblocks = size / CRYPT_SECTORS_PER_BUFSIZE;
  349. data.tot_numblocks = tot_size / CRYPT_SECTORS_PER_BUFSIZE;
  350. data.blocks_already_done = *size_already_done / CRYPT_SECTORS_PER_BUFSIZE;
  351. data.tot_used_blocks = get_num_blocks_used(f2fs_info);
  352. data.one_pct = data.tot_used_blocks / 100;
  353. data.cur_pct = 0;
  354. data.time_started = time(NULL);
  355. data.remaining_time = -1;
  356. data.buffer = (char*)malloc(f2fs_info->block_size);
  357. if (!data.buffer) {
  358. LOG(ERROR) << "Failed to allocate crypto buffer";
  359. goto errout;
  360. }
  361. data.count = 0;
  362. /* Currently, this either runs to completion, or hits a nonrecoverable error */
  363. rc = run_on_used_blocks(data.blocks_already_done, f2fs_info, &encrypt_one_block_f2fs, &data);
  364. if (rc) {
  365. LOG(ERROR) << "Error in running over f2fs blocks";
  366. rc = ENABLE_INPLACE_ERR_OTHER;
  367. goto errout;
  368. }
  369. *size_already_done += size;
  370. rc = 0;
  371. errout:
  372. if (rc) LOG(ERROR) << "Failed to encrypt f2fs filesystem on " << real_blkdev;
  373. log_progress_f2fs(0, true);
  374. free(f2fs_info);
  375. free(data.buffer);
  376. close(data.realfd);
  377. close(data.cryptofd);
  378. return rc;
  379. }
  380. static int cryptfs_enable_inplace_full(const char* crypto_blkdev, const char* real_blkdev,
  381. off64_t size, off64_t* size_already_done, off64_t tot_size,
  382. off64_t previously_encrypted_upto,
  383. bool set_progress_properties) {
  384. int realfd, cryptofd;
  385. char* buf[CRYPT_INPLACE_BUFSIZE];
  386. int rc = ENABLE_INPLACE_ERR_OTHER;
  387. off64_t numblocks, i, remainder;
  388. off64_t one_pct, cur_pct, new_pct;
  389. off64_t blocks_already_done, tot_numblocks;
  390. if ((realfd = open(real_blkdev, O_RDONLY | O_CLOEXEC)) < 0) {
  391. PLOG(ERROR) << "Error opening real_blkdev " << real_blkdev << " for inplace encrypt";
  392. return ENABLE_INPLACE_ERR_OTHER;
  393. }
  394. if ((cryptofd = open(crypto_blkdev, O_WRONLY | O_CLOEXEC)) < 0) {
  395. PLOG(ERROR) << "Error opening crypto_blkdev " << crypto_blkdev << " for inplace encrypt";
  396. close(realfd);
  397. return ENABLE_INPLACE_ERR_DEV;
  398. }
  399. /* This is pretty much a simple loop of reading 4K, and writing 4K.
  400. * The size passed in is the number of 512 byte sectors in the filesystem.
  401. * So compute the number of whole 4K blocks we should read/write,
  402. * and the remainder.
  403. */
  404. numblocks = size / CRYPT_SECTORS_PER_BUFSIZE;
  405. remainder = size % CRYPT_SECTORS_PER_BUFSIZE;
  406. tot_numblocks = tot_size / CRYPT_SECTORS_PER_BUFSIZE;
  407. blocks_already_done = *size_already_done / CRYPT_SECTORS_PER_BUFSIZE;
  408. LOG(ERROR) << "Encrypting filesystem in place...";
  409. i = previously_encrypted_upto + 1 - *size_already_done;
  410. if (lseek64(realfd, i * CRYPT_SECTOR_SIZE, SEEK_SET) < 0) {
  411. PLOG(ERROR) << "Cannot seek to previously encrypted point on " << real_blkdev;
  412. goto errout;
  413. }
  414. if (lseek64(cryptofd, i * CRYPT_SECTOR_SIZE, SEEK_SET) < 0) {
  415. PLOG(ERROR) << "Cannot seek to previously encrypted point on " << crypto_blkdev;
  416. goto errout;
  417. }
  418. for (; i < size && i % CRYPT_SECTORS_PER_BUFSIZE != 0; ++i) {
  419. if (unix_read(realfd, buf, CRYPT_SECTOR_SIZE) <= 0) {
  420. PLOG(ERROR) << "Error reading initial sectors from real_blkdev " << real_blkdev
  421. << " for inplace encrypt";
  422. goto errout;
  423. }
  424. if (unix_write(cryptofd, buf, CRYPT_SECTOR_SIZE) <= 0) {
  425. PLOG(ERROR) << "Error writing initial sectors to crypto_blkdev " << crypto_blkdev
  426. << " for inplace encrypt";
  427. goto errout;
  428. } else {
  429. LOG(INFO) << "Encrypted 1 block at " << i;
  430. }
  431. }
  432. one_pct = tot_numblocks / 100;
  433. cur_pct = 0;
  434. /* process the majority of the filesystem in blocks */
  435. for (i /= CRYPT_SECTORS_PER_BUFSIZE; i < numblocks; i++) {
  436. new_pct = (i + blocks_already_done) / one_pct;
  437. if (set_progress_properties && new_pct > cur_pct) {
  438. char property_buf[8];
  439. cur_pct = new_pct;
  440. snprintf(property_buf, sizeof(property_buf), "%" PRId64, cur_pct);
  441. android::base::SetProperty("vold.encrypt_progress", property_buf);
  442. }
  443. if (unix_read(realfd, buf, CRYPT_INPLACE_BUFSIZE) <= 0) {
  444. PLOG(ERROR) << "Error reading real_blkdev " << real_blkdev << " for inplace encrypt";
  445. goto errout;
  446. }
  447. if (unix_write(cryptofd, buf, CRYPT_INPLACE_BUFSIZE) <= 0) {
  448. PLOG(ERROR) << "Error writing crypto_blkdev " << crypto_blkdev << " for inplace encrypt";
  449. goto errout;
  450. } else {
  451. LOG(DEBUG) << "Encrypted " << CRYPT_SECTORS_PER_BUFSIZE << " block at "
  452. << i * CRYPT_SECTORS_PER_BUFSIZE;
  453. }
  454. }
  455. /* Do any remaining sectors */
  456. for (i = 0; i < remainder; i++) {
  457. if (unix_read(realfd, buf, CRYPT_SECTOR_SIZE) <= 0) {
  458. LOG(ERROR) << "Error reading final sectors from real_blkdev " << real_blkdev
  459. << " for inplace encrypt";
  460. goto errout;
  461. }
  462. if (unix_write(cryptofd, buf, CRYPT_SECTOR_SIZE) <= 0) {
  463. LOG(ERROR) << "Error writing final sectors to crypto_blkdev " << crypto_blkdev
  464. << " for inplace encrypt";
  465. goto errout;
  466. } else {
  467. LOG(INFO) << "Encrypted 1 block at next location";
  468. }
  469. }
  470. *size_already_done += size;
  471. rc = 0;
  472. errout:
  473. close(realfd);
  474. close(cryptofd);
  475. return rc;
  476. }
  477. /* returns on of the ENABLE_INPLACE_* return codes */
  478. int cryptfs_enable_inplace(const char* crypto_blkdev, const char* real_blkdev, off64_t size,
  479. off64_t* size_already_done, off64_t tot_size,
  480. off64_t previously_encrypted_upto, bool set_progress_properties) {
  481. int rc_ext4, rc_f2fs, rc_full;
  482. LOG(DEBUG) << "cryptfs_enable_inplace(" << crypto_blkdev << ", " << real_blkdev << ", " << size
  483. << ", " << size_already_done << ", " << tot_size << ", " << previously_encrypted_upto
  484. << ", " << set_progress_properties << ")";
  485. if (previously_encrypted_upto) {
  486. LOG(DEBUG) << "Continuing encryption from " << previously_encrypted_upto;
  487. }
  488. if (*size_already_done + size < previously_encrypted_upto) {
  489. LOG(DEBUG) << "cryptfs_enable_inplace already done";
  490. *size_already_done += size;
  491. return 0;
  492. }
  493. /* TODO: identify filesystem type.
  494. * As is, cryptfs_enable_inplace_ext4 will fail on an f2fs partition, and
  495. * then we will drop down to cryptfs_enable_inplace_f2fs.
  496. * */
  497. if ((rc_ext4 = cryptfs_enable_inplace_ext4(crypto_blkdev, real_blkdev, size, size_already_done,
  498. tot_size, previously_encrypted_upto,
  499. set_progress_properties)) == 0) {
  500. LOG(DEBUG) << "cryptfs_enable_inplace_ext4 success";
  501. return 0;
  502. }
  503. LOG(DEBUG) << "cryptfs_enable_inplace_ext4()=" << rc_ext4;
  504. if ((rc_f2fs = cryptfs_enable_inplace_f2fs(crypto_blkdev, real_blkdev, size, size_already_done,
  505. tot_size, previously_encrypted_upto,
  506. set_progress_properties)) == 0) {
  507. LOG(DEBUG) << "cryptfs_enable_inplace_f2fs success";
  508. return 0;
  509. }
  510. LOG(DEBUG) << "cryptfs_enable_inplace_f2fs()=" << rc_f2fs;
  511. rc_full =
  512. cryptfs_enable_inplace_full(crypto_blkdev, real_blkdev, size, size_already_done, tot_size,
  513. previously_encrypted_upto, set_progress_properties);
  514. LOG(DEBUG) << "cryptfs_enable_inplace_full()=" << rc_full;
  515. /* Hack for b/17898962, the following is the symptom... */
  516. if (rc_ext4 == ENABLE_INPLACE_ERR_DEV && rc_f2fs == ENABLE_INPLACE_ERR_DEV &&
  517. rc_full == ENABLE_INPLACE_ERR_DEV) {
  518. LOG(DEBUG) << "ENABLE_INPLACE_ERR_DEV";
  519. return ENABLE_INPLACE_ERR_DEV;
  520. }
  521. return rc_full;
  522. }