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