OSDN Git Service

resolved conflicts for merge of afa60cee to master
authorElliott Hughes <enh@google.com>
Thu, 26 Jun 2014 01:25:11 +0000 (18:25 -0700)
committerElliott Hughes <enh@google.com>
Thu, 26 Jun 2014 01:31:47 +0000 (18:31 -0700)
Change-Id: I1568def8839bed4d4d2dadbd97194d5603edc627

1  2 
cryptfs.c

diff --cc cryptfs.c
+++ b/cryptfs.c
@@@ -23,8 -23,8 +23,9 @@@
  #include <sys/types.h>
  #include <sys/wait.h>
  #include <sys/stat.h>
 +#include <ctype.h>
  #include <fcntl.h>
+ #include <inttypes.h>
  #include <unistd.h>
  #include <stdio.h>
  #include <sys/ioctl.h>
@@@ -1842,16 -1455,22 +1843,16 @@@ static int cryptfs_enable_wipe(char *cr
          num_args = 6;
          SLOGI("Making empty filesystem with command %s %s %s %s %s %s\n",
                args[0], args[1], args[2], args[3], args[4], args[5]);
 -    } else if (type== FAT_FS) {
 -        args[0] = "/system/bin/newfs_msdos";
 -        args[1] = "-F";
 -        args[2] = "32";
 -        args[3] = "-O";
 -        args[4] = "android";
 -        args[5] = "-c";
 -        args[6] = "8";
 -        args[7] = "-s";
 +    } else if (type == F2FS_FS) {
 +        args[0] = "/system/bin/mkfs.f2fs";
 +        args[1] = "-t";
 +        args[2] = "-d1";
 +        args[3] = crypto_blkdev;
-         snprintf(size_str, sizeof(size_str), "%lld", size);
+         snprintf(size_str, sizeof(size_str), "%" PRId64, size);
 -        args[8] = size_str;
 -        args[9] = crypto_blkdev;
 -        num_args = 10;
 -        SLOGI("Making empty filesystem with command %s %s %s %s %s %s %s %s %s %s\n",
 -              args[0], args[1], args[2], args[3], args[4], args[5],
 -              args[6], args[7], args[8], args[9]);
 +        args[4] = size_str;
 +        num_args = 5;
 +        SLOGI("Making empty filesystem with command %s %s %s %s %s\n",
 +              args[0], args[1], args[2], args[3], args[4]);
      } else {
          SLOGE("cryptfs_enable_wipe(): unknown filesystem type %d\n", type);
          return -1;
  }
  
  #define CRYPT_INPLACE_BUFSIZE 4096
 -#define CRYPT_SECTORS_PER_BUFSIZE (CRYPT_INPLACE_BUFSIZE / 512)
 -static int cryptfs_enable_inplace(char *crypto_blkdev, char *real_blkdev, off64_t size,
 -                                  off64_t *size_already_done, off64_t tot_size)
 +#define CRYPT_SECTORS_PER_BUFSIZE (CRYPT_INPLACE_BUFSIZE / CRYPT_SECTOR_SIZE)
 +#define CRYPT_SECTOR_SIZE 512
 +
 +/* aligned 32K writes tends to make flash happy.
 + * SD card association recommends it.
 + */
 +#define BLOCKS_AT_A_TIME 8
 +
 +struct encryptGroupsData
  {
 -    int realfd, cryptofd;
 -    char *buf[CRYPT_INPLACE_BUFSIZE];
 -    int rc = -1;
 -    off64_t numblocks, i, remainder;
 +    int realfd;
 +    int cryptofd;
 +    off64_t numblocks;
      off64_t one_pct, cur_pct, new_pct;
      off64_t blocks_already_done, tot_numblocks;
 +    off64_t used_blocks_already_done, tot_used_blocks;
 +    char* real_blkdev, * crypto_blkdev;
 +    int count;
 +    off64_t offset;
 +    char* buffer;
 +    off64_t last_written_sector;
 +    int completed;
 +    time_t time_started;
 +    int remaining_time;
 +};
 +
 +static void update_progress(struct encryptGroupsData* data, int is_used)
 +{
 +    data->blocks_already_done++;
  
 -    if ( (realfd = open(real_blkdev, O_RDONLY)) < 0) { 
 -        SLOGE("Error opening real_blkdev %s for inplace encrypt\n", real_blkdev);
 -        return -1;
 +    if (is_used) {
 +        data->used_blocks_already_done++;
      }
  
 -    if ( (cryptofd = open(crypto_blkdev, O_WRONLY)) < 0) { 
 -        SLOGE("Error opening crypto_blkdev %s for inplace encrypt\n", crypto_blkdev);
 -        close(realfd);
 -        return -1;
 +    if (data->tot_used_blocks) {
 +        data->new_pct = data->used_blocks_already_done / data->one_pct;
 +    } else {
 +        data->new_pct = data->blocks_already_done / data->one_pct;
      }
  
 -    /* This is pretty much a simple loop of reading 4K, and writing 4K.
 -     * The size passed in is the number of 512 byte sectors in the filesystem.
 -     * So compute the number of whole 4K blocks we should read/write,
 -     * and the remainder.
 -     */
 -    numblocks = size / CRYPT_SECTORS_PER_BUFSIZE;
 -    remainder = size % CRYPT_SECTORS_PER_BUFSIZE;
 -    tot_numblocks = tot_size / CRYPT_SECTORS_PER_BUFSIZE;
 -    blocks_already_done = *size_already_done / CRYPT_SECTORS_PER_BUFSIZE;
 -
 -    SLOGE("Encrypting filesystem in place...");
 +    if (data->new_pct > data->cur_pct) {
 +        char buf[8];
 +        data->cur_pct = data->new_pct;
-         snprintf(buf, sizeof(buf), "%lld", data->cur_pct);
++        snprintf(buf, sizeof(buf), "%" PRId64, data->cur_pct);
 +        property_set("vold.encrypt_progress", buf);
-         SLOGI("Encrypted %lld percent of drive", data->cur_pct);
++        SLOGI("Encrypted %" PRId64 " percent of drive", data->cur_pct);
 +    }
  
 -    one_pct = tot_numblocks / 100;
 -    cur_pct = 0;
 -    /* process the majority of the filesystem in blocks */
 -    for (i=0; i<numblocks; i++) {
 -        new_pct = (i + blocks_already_done) / one_pct;
 -        if (new_pct > cur_pct) {
 +    if (data->cur_pct >= 5) {
 +        double elapsed_time = difftime(time(NULL), data->time_started);
 +        off64_t remaining_blocks = data->tot_used_blocks
 +                                   - data->used_blocks_already_done;
 +        int remaining_time = (int)(elapsed_time * remaining_blocks
 +                                   / data->used_blocks_already_done);
 +        if (data->remaining_time == -1
 +            || remaining_time < data->remaining_time) {
              char buf[8];
 +            snprintf(buf, sizeof(buf), "%d", remaining_time);
 +            property_set("vold.encrypt_time_remaining", buf);
  
-             SLOGI("Encrypted %lld percent of drive, %d seconds to go",
 -            cur_pct = new_pct;
 -            snprintf(buf, sizeof(buf), "%" PRId64, cur_pct);
 -            property_set("vold.encrypt_progress", buf);
 -        }
 -        if (unix_read(realfd, buf, CRYPT_INPLACE_BUFSIZE) <= 0) {
 -            SLOGE("Error reading real_blkdev %s for inplace encrypt\n", crypto_blkdev);
 -            goto errout;
 -        }
 -        if (unix_write(cryptofd, buf, CRYPT_INPLACE_BUFSIZE) <= 0) {
 -            SLOGE("Error writing crypto_blkdev %s for inplace encrypt\n", crypto_blkdev);
 -            goto errout;
++            SLOGI("Encrypted %" PRId64 " percent of drive, %d seconds to go",
 +                  data->cur_pct, remaining_time);
 +            data->remaining_time = remaining_time;
 +        }
 +    }
 +}
 +
 +static int flush_outstanding_data(struct encryptGroupsData* data)
 +{
 +    if (data->count == 0) {
 +        return 0;
 +    }
 +
-     SLOGV("Copying %d blocks at offset %llx", data->count, data->offset);
++    SLOGV("Copying %d blocks at offset %" PRId64, data->count, data->offset);
 +
 +    if (pread64(data->realfd, data->buffer,
 +                info.block_size * data->count, data->offset)
 +        <= 0) {
 +        SLOGE("Error reading real_blkdev %s for inplace encrypt",
 +              data->real_blkdev);
 +        return -1;
 +    }
 +
 +    if (pwrite64(data->cryptofd, data->buffer,
 +                 info.block_size * data->count, data->offset)
 +        <= 0) {
 +        SLOGE("Error writing crypto_blkdev %s for inplace encrypt",
 +              data->crypto_blkdev);
 +        return -1;
 +    } else {
-         SLOGI("Encrypted %d blocks at sector %lld",
++        SLOGI("Encrypted %d blocks at sector %" PRId64,
 +              data->count, data->offset / info.block_size * CRYPT_SECTOR_SIZE);
 +    }
 +
 +    data->count = 0;
 +    data->last_written_sector = (data->offset + data->count)
 +                                / info.block_size * CRYPT_SECTOR_SIZE - 1;
 +    return 0;
 +}
 +
 +static int encrypt_groups(struct encryptGroupsData* data)
 +{
 +    unsigned int i;
 +    u8 *block_bitmap = 0;
 +    unsigned int block;
 +    off64_t ret;
 +    int rc = -1;
 +
 +    data->buffer = malloc(info.block_size * BLOCKS_AT_A_TIME);
 +    if (!data->buffer) {
 +        SLOGE("Failed to allocate crypto buffer");
 +        goto errout;
 +    }
 +
 +    block_bitmap = malloc(info.block_size);
 +    if (!block_bitmap) {
 +        SLOGE("failed to allocate block bitmap");
 +        goto errout;
 +    }
 +
 +    for (i = 0; i < aux_info.groups; ++i) {
 +        SLOGI("Encrypting group %d", i);
 +
 +        u32 first_block = aux_info.first_data_block + i * info.blocks_per_group;
 +        u32 block_count = min(info.blocks_per_group,
 +                             aux_info.len_blocks - first_block);
 +
 +        off64_t offset = (u64)info.block_size
 +                         * aux_info.bg_desc[i].bg_block_bitmap;
 +
 +        ret = pread64(data->realfd, block_bitmap, info.block_size, offset);
 +        if (ret != (int)info.block_size) {
 +            SLOGE("failed to read all of block group bitmap %d", i);
 +            goto errout;
 +        }
 +
 +        offset = (u64)info.block_size * first_block;
 +
 +        data->count = 0;
 +
 +        for (block = 0; block < block_count; block++) {
 +            int used = bitmap_get_bit(block_bitmap, block);
 +            update_progress(data, used);
 +            if (used) {
 +                if (data->count == 0) {
 +                    data->offset = offset;
 +                }
 +                data->count++;
 +            } else {
 +                if (flush_outstanding_data(data)) {
 +                    goto errout;
 +                }
 +            }
 +
 +            offset += info.block_size;
 +
 +            /* Write data if we are aligned or buffer size reached */
 +            if (offset % (info.block_size * BLOCKS_AT_A_TIME) == 0
 +                || data->count == BLOCKS_AT_A_TIME) {
 +                if (flush_outstanding_data(data)) {
 +                    goto errout;
 +                }
 +            }
 +
 +            if (!is_battery_ok_to_continue()) {
 +                SLOGE("Stopping encryption due to low battery");
 +                rc = 0;
 +                goto errout;
 +            }
 +
 +        }
 +        if (flush_outstanding_data(data)) {
 +            goto errout;
 +        }
 +    }
 +
 +    data->completed = 1;
 +    rc = 0;
 +
 +errout:
 +    free(data->buffer);
 +    free(block_bitmap);
 +    return rc;
 +}
 +
 +static int cryptfs_enable_inplace_ext4(char *crypto_blkdev,
 +                                       char *real_blkdev,
 +                                       off64_t size,
 +                                       off64_t *size_already_done,
 +                                       off64_t tot_size,
 +                                       off64_t previously_encrypted_upto)
 +{
 +    u32 i;
 +    struct encryptGroupsData data;
 +    int rc = -1;
 +
 +    if (previously_encrypted_upto > *size_already_done) {
 +        SLOGD("Not fast encrypting since resuming part way through");
 +        return -1;
 +    }
 +
 +    memset(&data, 0, sizeof(data));
 +    data.real_blkdev = real_blkdev;
 +    data.crypto_blkdev = crypto_blkdev;
 +
 +    if ( (data.realfd = open(real_blkdev, O_RDWR)) < 0) {
 +        SLOGE("Error opening real_blkdev %s for inplace encrypt\n",
 +              real_blkdev);
 +        goto errout;
 +    }
 +
 +    if ( (data.cryptofd = open(crypto_blkdev, O_WRONLY)) < 0) {
 +        SLOGE("Error opening crypto_blkdev %s for inplace encrypt\n",
 +              crypto_blkdev);
 +        goto errout;
 +    }
 +
 +    if (setjmp(setjmp_env)) {
 +        SLOGE("Reading extent caused an exception");
 +        goto errout;
 +    }
 +
 +    if (read_ext(data.realfd, 0) != 0) {
 +        SLOGE("Failed to read extent");
 +        goto errout;
 +    }
 +
 +    data.numblocks = size / CRYPT_SECTORS_PER_BUFSIZE;
 +    data.tot_numblocks = tot_size / CRYPT_SECTORS_PER_BUFSIZE;
 +    data.blocks_already_done = *size_already_done / CRYPT_SECTORS_PER_BUFSIZE;
 +
 +    SLOGI("Encrypting filesystem in place...");
 +
 +    data.tot_used_blocks = data.numblocks;
 +    for (i = 0; i < aux_info.groups; ++i) {
 +      data.tot_used_blocks -= aux_info.bg_desc[i].bg_free_blocks_count;
 +    }
 +
 +    data.one_pct = data.tot_used_blocks / 100;
 +    data.cur_pct = 0;
 +    data.time_started = time(NULL);
 +    data.remaining_time = -1;
 +
 +    rc = encrypt_groups(&data);
 +    if (rc) {
 +        SLOGE("Error encrypting groups");
 +        goto errout;
 +    }
 +
 +    *size_already_done += data.completed ? size : data.last_written_sector;
 +    rc = 0;
 +
 +errout:
 +    close(data.realfd);
 +    close(data.cryptofd);
 +
 +    return rc;
 +}
 +
 +static int cryptfs_enable_inplace_full(char *crypto_blkdev, char *real_blkdev,
 +                                       off64_t size, off64_t *size_already_done,
 +                                       off64_t tot_size,
 +                                       off64_t previously_encrypted_upto)
 +{
 +    int realfd, cryptofd;
 +    char *buf[CRYPT_INPLACE_BUFSIZE];
 +    int rc = -1;
 +    off64_t numblocks, i, remainder;
 +    off64_t one_pct, cur_pct, new_pct;
 +    off64_t blocks_already_done, tot_numblocks;
 +
 +    if ( (realfd = open(real_blkdev, O_RDONLY)) < 0) { 
 +        SLOGE("Error opening real_blkdev %s for inplace encrypt\n", real_blkdev);
 +        return -1;
 +    }
 +
 +    if ( (cryptofd = open(crypto_blkdev, O_WRONLY)) < 0) { 
 +        SLOGE("Error opening crypto_blkdev %s for inplace encrypt\n", crypto_blkdev);
 +        close(realfd);
 +        return -1;
 +    }
 +
 +    /* This is pretty much a simple loop of reading 4K, and writing 4K.
 +     * The size passed in is the number of 512 byte sectors in the filesystem.
 +     * So compute the number of whole 4K blocks we should read/write,
 +     * and the remainder.
 +     */
 +    numblocks = size / CRYPT_SECTORS_PER_BUFSIZE;
 +    remainder = size % CRYPT_SECTORS_PER_BUFSIZE;
 +    tot_numblocks = tot_size / CRYPT_SECTORS_PER_BUFSIZE;
 +    blocks_already_done = *size_already_done / CRYPT_SECTORS_PER_BUFSIZE;
 +
 +    SLOGE("Encrypting filesystem in place...");
 +
 +    i = previously_encrypted_upto + 1 - *size_already_done;
 +
 +    if (lseek64(realfd, i * CRYPT_SECTOR_SIZE, SEEK_SET) < 0) {
 +        SLOGE("Cannot seek to previously encrypted point on %s", real_blkdev);
 +        goto errout;
 +    }
 +
 +    if (lseek64(cryptofd, i * CRYPT_SECTOR_SIZE, SEEK_SET) < 0) {
 +        SLOGE("Cannot seek to previously encrypted point on %s", crypto_blkdev);
 +        goto errout;
 +    }
 +
 +    for (;i < size && i % CRYPT_SECTORS_PER_BUFSIZE != 0; ++i) {
 +        if (unix_read(realfd, buf, CRYPT_SECTOR_SIZE) <= 0) {
 +            SLOGE("Error reading initial sectors from real_blkdev %s for "
 +                  "inplace encrypt\n", crypto_blkdev);
 +            goto errout;
 +        }
 +        if (unix_write(cryptofd, buf, CRYPT_SECTOR_SIZE) <= 0) {
 +            SLOGE("Error writing initial sectors to crypto_blkdev %s for "
 +                  "inplace encrypt\n", crypto_blkdev);
 +            goto errout;
 +        } else {
-             SLOGI("Encrypted 1 block at %lld", i);
++            SLOGI("Encrypted 1 block at %" PRId64, i);
 +        }
 +    }
 +
 +    one_pct = tot_numblocks / 100;
 +    cur_pct = 0;
 +    /* process the majority of the filesystem in blocks */
 +    for (i/=CRYPT_SECTORS_PER_BUFSIZE; i<numblocks; i++) {
 +        new_pct = (i + blocks_already_done) / one_pct;
 +        if (new_pct > cur_pct) {
 +            char buf[8];
 +
 +            cur_pct = new_pct;
-             snprintf(buf, sizeof(buf), "%lld", cur_pct);
++            snprintf(buf, sizeof(buf), "%" PRId64, cur_pct);
 +            property_set("vold.encrypt_progress", buf);
 +        }
 +        if (unix_read(realfd, buf, CRYPT_INPLACE_BUFSIZE) <= 0) {
 +            SLOGE("Error reading real_blkdev %s for inplace encrypt", crypto_blkdev);
 +            goto errout;
 +        }
 +        if (unix_write(cryptofd, buf, CRYPT_INPLACE_BUFSIZE) <= 0) {
 +            SLOGE("Error writing crypto_blkdev %s for inplace encrypt", crypto_blkdev);
 +            goto errout;
 +        } else {
-             SLOGD("Encrypted %d block at %lld",
++            SLOGD("Encrypted %d block at %" PRId64,
 +                  CRYPT_SECTORS_PER_BUFSIZE,
 +                  i * CRYPT_SECTORS_PER_BUFSIZE);
 +        }
 +
 +       if (!is_battery_ok_to_continue()) {
 +            SLOGE("Stopping encryption due to low battery");
 +            *size_already_done += (i + 1) * CRYPT_SECTORS_PER_BUFSIZE - 1;
 +            rc = 0;
 +            goto errout;
          }
      }
  
@@@ -2257,31 -1576,6 +2258,31 @@@ errout
      return rc;
  }
  
-         SLOGD("Continuing encryption from %lld", previously_encrypted_upto);
 +static int cryptfs_enable_inplace(char *crypto_blkdev, char *real_blkdev,
 +                                  off64_t size, off64_t *size_already_done,
 +                                  off64_t tot_size,
 +                                  off64_t previously_encrypted_upto)
 +{
 +    if (previously_encrypted_upto) {
++        SLOGD("Continuing encryption from %" PRId64, previously_encrypted_upto);
 +    }
 +
 +    if (*size_already_done + size < previously_encrypted_upto) {
 +        *size_already_done += size;
 +        return 0;
 +    }
 +
 +    if (cryptfs_enable_inplace_ext4(crypto_blkdev, real_blkdev,
 +                                    size, size_already_done,
 +                                    tot_size, previously_encrypted_upto) == 0) {
 +        return 0;
 +    }
 +
 +    return cryptfs_enable_inplace_full(crypto_blkdev, real_blkdev,
 +                                       size, size_already_done, tot_size,
 +                                       previously_encrypted_upto);
 +}
 +
  #define CRYPTO_ENABLE_WIPE 1
  #define CRYPTO_ENABLE_INPLACE 2