diff options
Diffstat (limited to 'xlators/encryption/crypt/src/data.c')
-rw-r--r-- | xlators/encryption/crypt/src/data.c | 1131 |
1 files changed, 541 insertions, 590 deletions
diff --git a/xlators/encryption/crypt/src/data.c b/xlators/encryption/crypt/src/data.c index 0aae60d7139..8e8701b6bf2 100644 --- a/xlators/encryption/crypt/src/data.c +++ b/xlators/encryption/crypt/src/data.c @@ -12,136 +12,130 @@ #include "crypt-common.h" #include "crypt.h" -static void set_iv_aes_xts(off_t offset, struct object_cipher_info *object) +static void +set_iv_aes_xts(off_t offset, struct object_cipher_info *object) { - unsigned char *ivec; + unsigned char *ivec; - ivec = object->u.aes_xts.ivec; + ivec = object->u.aes_xts.ivec; - /* convert the tweak into a little-endian byte - * array (IEEE P1619/D16, May 2007, section 5.1) - */ + /* convert the tweak into a little-endian byte + * array (IEEE P1619/D16, May 2007, section 5.1) + */ - *((uint64_t *)ivec) = htole64(offset); + *((uint64_t *)ivec) = htole64(offset); - /* ivec is padded with zeroes */ + /* ivec is padded with zeroes */ } -static int32_t aes_set_keys_common(unsigned char *raw_key, uint32_t key_size, - AES_KEY *keys) +static int32_t +aes_set_keys_common(unsigned char *raw_key, uint32_t key_size, AES_KEY *keys) { - int32_t ret; - - ret = AES_set_encrypt_key(raw_key, - key_size, - &keys[AES_ENCRYPT]); - if (ret) { - gf_log("crypt", GF_LOG_ERROR, "Set encrypt key failed"); - return ret; - } - ret = AES_set_decrypt_key(raw_key, - key_size, - &keys[AES_DECRYPT]); - if (ret) { - gf_log("crypt", GF_LOG_ERROR, "Set decrypt key failed"); - return ret; - } - return 0; + int32_t ret; + + ret = AES_set_encrypt_key(raw_key, key_size, &keys[AES_ENCRYPT]); + if (ret) { + gf_log("crypt", GF_LOG_ERROR, "Set encrypt key failed"); + return ret; + } + ret = AES_set_decrypt_key(raw_key, key_size, &keys[AES_DECRYPT]); + if (ret) { + gf_log("crypt", GF_LOG_ERROR, "Set decrypt key failed"); + return ret; + } + return 0; } /* * set private cipher info for xts mode */ -static int32_t set_private_aes_xts(struct crypt_inode_info *info, - struct master_cipher_info *master) +static int32_t +set_private_aes_xts(struct crypt_inode_info *info, + struct master_cipher_info *master) { - int ret; - struct object_cipher_info *object = get_object_cinfo(info); - unsigned char *data_key; - uint32_t subkey_size; - - /* init tweak value */ - memset(object->u.aes_xts.ivec, 0, 16); - - data_key = GF_CALLOC(1, object->o_dkey_size, gf_crypt_mt_key); - if (!data_key) - return ENOMEM; - - /* - * retrieve data keying material - */ - ret = get_data_file_key(info, master, object->o_dkey_size, data_key); - if (ret) { - gf_log("crypt", GF_LOG_ERROR, "Failed to retrieve data key"); - GF_FREE(data_key); - return ret; - } - /* - * parse compound xts key - */ - subkey_size = object->o_dkey_size >> 4; /* (xts-key-size-in-bytes / 2) */ - /* - * install key for data encryption - */ - ret = aes_set_keys_common(data_key, - subkey_size << 3, object->u.aes_xts.dkey); - if (ret) { - GF_FREE(data_key); - return ret; - } - /* - * set up key used to encrypt tweaks - */ - ret = AES_set_encrypt_key(data_key + subkey_size, - object->o_dkey_size / 2, - &object->u.aes_xts.tkey); - if (ret < 0) - gf_log("crypt", GF_LOG_ERROR, "Set tweak key failed"); - - GF_FREE(data_key); - return ret; + int ret; + struct object_cipher_info *object = get_object_cinfo(info); + unsigned char *data_key; + uint32_t subkey_size; + + /* init tweak value */ + memset(object->u.aes_xts.ivec, 0, 16); + + data_key = GF_CALLOC(1, object->o_dkey_size, gf_crypt_mt_key); + if (!data_key) + return ENOMEM; + + /* + * retrieve data keying material + */ + ret = get_data_file_key(info, master, object->o_dkey_size, data_key); + if (ret) { + gf_log("crypt", GF_LOG_ERROR, "Failed to retrieve data key"); + GF_FREE(data_key); + return ret; + } + /* + * parse compound xts key + */ + subkey_size = object->o_dkey_size >> 4; /* (xts-key-size-in-bytes / 2) */ + /* + * install key for data encryption + */ + ret = aes_set_keys_common(data_key, subkey_size << 3, + object->u.aes_xts.dkey); + if (ret) { + GF_FREE(data_key); + return ret; + } + /* + * set up key used to encrypt tweaks + */ + ret = AES_set_encrypt_key(data_key + subkey_size, object->o_dkey_size / 2, + &object->u.aes_xts.tkey); + if (ret < 0) + gf_log("crypt", GF_LOG_ERROR, "Set tweak key failed"); + + GF_FREE(data_key); + return ret; } -static int32_t aes_xts_init(void) +static int32_t +aes_xts_init(void) { - cassert(AES_BLOCK_SIZE == (1 << AES_BLOCK_BITS)); - return 0; + cassert(AES_BLOCK_SIZE == (1 << AES_BLOCK_BITS)); + return 0; } -static int32_t check_key_aes_xts(uint32_t keysize) +static int32_t +check_key_aes_xts(uint32_t keysize) { - switch(keysize) { - case 256: - case 512: - return 0; - default: - break; - } - return -1; + switch (keysize) { + case 256: + case 512: + return 0; + default: + break; + } + return -1; } -static int32_t encrypt_aes_xts(const unsigned char *from, - unsigned char *to, size_t length, - off_t offset, const int enc, - struct object_cipher_info *object) +static int32_t +encrypt_aes_xts(const unsigned char *from, unsigned char *to, size_t length, + off_t offset, const int enc, struct object_cipher_info *object) { - XTS128_CONTEXT ctx; - if (enc) { - ctx.key1 = &object->u.aes_xts.dkey[AES_ENCRYPT]; - ctx.block1 = (block128_f)AES_encrypt; - } - else { - ctx.key1 = &object->u.aes_xts.dkey[AES_DECRYPT]; - ctx.block1 = (block128_f)AES_decrypt; - } - ctx.key2 = &object->u.aes_xts.tkey; - ctx.block2 = (block128_f)AES_encrypt; - - return CRYPTO_xts128_encrypt(&ctx, - object->u.aes_xts.ivec, - from, - to, - length, enc); + XTS128_CONTEXT ctx; + if (enc) { + ctx.key1 = &object->u.aes_xts.dkey[AES_ENCRYPT]; + ctx.block1 = (block128_f)AES_encrypt; + } else { + ctx.key1 = &object->u.aes_xts.dkey[AES_DECRYPT]; + ctx.block1 = (block128_f)AES_decrypt; + } + ctx.key2 = &object->u.aes_xts.tkey; + ctx.block2 = (block128_f)AES_encrypt; + + return CRYPTO_xts128_encrypt(&ctx, object->u.aes_xts.ivec, from, to, length, + enc); } /* @@ -149,26 +143,19 @@ static int32_t encrypt_aes_xts(const unsigned char *from, * @to: result of cipher transform; * @off: offset in a file (must be cblock-aligned); */ -static void cipher_data(struct object_cipher_info *object, - char *from, - char *to, - off_t off, - size_t len, - const int enc) +static void +cipher_data(struct object_cipher_info *object, char *from, char *to, off_t off, + size_t len, const int enc) { - crypt_check_input_len(len, object); + crypt_check_input_len(len, object); #if TRIVIAL_TFM && DEBUG_CRYPT - return; + return; #endif - data_cipher_algs[object->o_alg][object->o_mode].set_iv(off, object); - data_cipher_algs[object->o_alg][object->o_mode].encrypt - ((const unsigned char *)from, - (unsigned char *)to, - len, - off, - enc, - object); + data_cipher_algs[object->o_alg][object->o_mode].set_iv(off, object); + data_cipher_algs[object->o_alg][object->o_mode].encrypt( + (const unsigned char *)from, (unsigned char *)to, len, off, enc, + object); } #define MAX_CIPHER_CHUNK (1 << 30) @@ -184,32 +171,24 @@ static void cipher_data(struct object_cipher_info *object, * for other modes). * @dir: direction of transform (encrypt/decrypt). */ -static void cipher_region(struct object_cipher_info *object, - char *from, - char *to, - off_t off, - size_t len, - int dir) +static void +cipher_region(struct object_cipher_info *object, char *from, char *to, + off_t off, size_t len, int dir) { - while (len > 0) { - size_t to_cipher; - - to_cipher = len; - if (to_cipher > MAX_CIPHER_CHUNK) - to_cipher = MAX_CIPHER_CHUNK; - - /* this will reset IV */ - cipher_data(object, - from, - to, - off, - to_cipher, - dir); - from += to_cipher; - to += to_cipher; - off += to_cipher; - len -= to_cipher; - } + while (len > 0) { + size_t to_cipher; + + to_cipher = len; + if (to_cipher > MAX_CIPHER_CHUNK) + to_cipher = MAX_CIPHER_CHUNK; + + /* this will reset IV */ + cipher_data(object, from, to, off, to_cipher, dir); + from += to_cipher; + to += to_cipher; + off += to_cipher; + len -= to_cipher; + } } /* @@ -224,115 +203,105 @@ static void cipher_region(struct object_cipher_info *object, * responsible for this. @dir is "direction" of * transform (encrypt/decrypt). */ -static void cipher_aligned_iov(struct object_cipher_info *object, - struct iovec *vec, - int count, - off_t off, - int32_t dir) +static void +cipher_aligned_iov(struct object_cipher_info *object, struct iovec *vec, + int count, off_t off, int32_t dir) { - int i; - int len = 0; - - for (i = 0; i < count; i++) { - cipher_region(object, - vec[i].iov_base, - vec[i].iov_base, - off + len, - vec[i].iov_len, - dir); - len += vec[i].iov_len; - } + int i; + int len = 0; + + for (i = 0; i < count; i++) { + cipher_region(object, vec[i].iov_base, vec[i].iov_base, off + len, + vec[i].iov_len, dir); + len += vec[i].iov_len; + } } -void encrypt_aligned_iov(struct object_cipher_info *object, - struct iovec *vec, - int count, - off_t off) +void +encrypt_aligned_iov(struct object_cipher_info *object, struct iovec *vec, + int count, off_t off) { - cipher_aligned_iov(object, vec, count, off, 1); + cipher_aligned_iov(object, vec, count, off, 1); } -void decrypt_aligned_iov(struct object_cipher_info *object, - struct iovec *vec, - int count, - off_t off) +void +decrypt_aligned_iov(struct object_cipher_info *object, struct iovec *vec, + int count, off_t off) { - cipher_aligned_iov(object, vec, count, off, 0); + cipher_aligned_iov(object, vec, count, off, 0); } #if DEBUG_CRYPT -static void compound_stream(struct iovec *vec, int count, char *buf, off_t skip) +static void +compound_stream(struct iovec *vec, int count, char *buf, off_t skip) { - int i; - int off = 0; - for (i = 0; i < count; i++) { - memcpy(buf + off, - vec[i].iov_base + skip, - vec[i].iov_len - skip); - - off += (vec[i].iov_len - skip); - skip = 0; - } + int i; + int off = 0; + for (i = 0; i < count; i++) { + memcpy(buf + off, vec[i].iov_base + skip, vec[i].iov_len - skip); + + off += (vec[i].iov_len - skip); + skip = 0; + } } -static void check_iovecs(struct iovec *vec, int cnt, - struct iovec *avec, int acnt, uint32_t off_in_head) +static void +check_iovecs(struct iovec *vec, int cnt, struct iovec *avec, int acnt, + uint32_t off_in_head) { - char *s1, *s2; - uint32_t size, asize; - - size = iov_length(vec, cnt); - asize = iov_length(avec, acnt) - off_in_head; - if (size != asize) { - gf_log("crypt", GF_LOG_DEBUG, "size %d is not eq asize %d", - size, asize); - return; - } - s1 = GF_CALLOC(1, size, gf_crypt_mt_data); - if (!s1) { - gf_log("crypt", GF_LOG_DEBUG, "Can not allocate stream "); - return; - } - s2 = GF_CALLOC(1, asize, gf_crypt_mt_data); - if (!s2) { - GF_FREE(s1); - gf_log("crypt", GF_LOG_DEBUG, "Can not allocate stream "); - return; - } - compound_stream(vec, cnt, s1, 0); - compound_stream(avec, acnt, s2, off_in_head); - if (memcmp(s1, s2, size)) - gf_log("crypt", GF_LOG_DEBUG, "chunks of different data"); - GF_FREE(s1); - GF_FREE(s2); + char *s1, *s2; + uint32_t size, asize; + + size = iov_length(vec, cnt); + asize = iov_length(avec, acnt) - off_in_head; + if (size != asize) { + gf_log("crypt", GF_LOG_DEBUG, "size %d is not eq asize %d", size, + asize); + return; + } + s1 = GF_CALLOC(1, size, gf_crypt_mt_data); + if (!s1) { + gf_log("crypt", GF_LOG_DEBUG, "Can not allocate stream "); + return; + } + s2 = GF_CALLOC(1, asize, gf_crypt_mt_data); + if (!s2) { + GF_FREE(s1); + gf_log("crypt", GF_LOG_DEBUG, "Can not allocate stream "); + return; + } + compound_stream(vec, cnt, s1, 0); + compound_stream(avec, acnt, s2, off_in_head); + if (memcmp(s1, s2, size)) + gf_log("crypt", GF_LOG_DEBUG, "chunks of different data"); + GF_FREE(s1); + GF_FREE(s2); } #else #define check_iovecs(vec, count, avec, avecn, off) noop #endif /* DEBUG_CRYPT */ -static char *data_alloc_block(xlator_t *this, crypt_local_t *local, - int32_t block_size) +static char * +data_alloc_block(xlator_t *this, crypt_local_t *local, int32_t block_size) { - struct iobuf *iobuf = NULL; - - iobuf = iobuf_get2(this->ctx->iobuf_pool, block_size); - if (!iobuf) { - gf_log("crypt", GF_LOG_ERROR, - "Failed to get iobuf"); - return NULL; - } - if (!local->iobref_data) { - local->iobref_data = iobref_new(); - if (!local->iobref_data) { - gf_log("crypt", GF_LOG_ERROR, - "Failed to get iobref"); - iobuf_unref(iobuf); - return NULL; - } - } - iobref_add(local->iobref_data, iobuf); - return iobuf->ptr; + struct iobuf *iobuf = NULL; + + iobuf = iobuf_get2(this->ctx->iobuf_pool, block_size); + if (!iobuf) { + gf_log("crypt", GF_LOG_ERROR, "Failed to get iobuf"); + return NULL; + } + if (!local->iobref_data) { + local->iobref_data = iobref_new(); + if (!local->iobref_data) { + gf_log("crypt", GF_LOG_ERROR, "Failed to get iobref"); + iobuf_unref(iobuf); + return NULL; + } + } + iobref_add(local->iobref_data, iobuf); + return iobuf->ptr; } /* @@ -360,250 +329,239 @@ static char *data_alloc_block(xlator_t *this, crypt_local_t *local, * 3 - full non-compound (the case of reuse); * 4 - incomplete non-compound (tail). */ -int32_t align_iov_by_atoms(xlator_t *this, - crypt_local_t *local, - struct object_cipher_info *object, - struct iovec *vec /* input vector */, - int32_t count /* number of vec components */, - struct iovec *avec /* aligned vector */, - char **blocks /* pool of blocks */, - uint32_t *blocks_allocated, - struct avec_config *conf) +int32_t +align_iov_by_atoms(xlator_t *this, crypt_local_t *local, + struct object_cipher_info *object, + struct iovec *vec /* input vector */, + int32_t count /* number of vec components */, + struct iovec *avec /* aligned vector */, + char **blocks /* pool of blocks */, + uint32_t *blocks_allocated, struct avec_config *conf) { - int vecn = 0; /* number of the current component in vec */ - int avecn = 0; /* number of the current component in avec */ - off_t vec_off = 0; /* offset in the current vec component, - * i.e. the number of bytes have already - * been copied */ - int32_t block_size = get_atom_size(object); - size_t to_process; /* number of vec's bytes to copy and(or) re-use */ - int32_t off_in_head = conf->off_in_head; - - to_process = iov_length(vec, count); - - while (to_process > 0) { - if (off_in_head || - vec[vecn].iov_len - vec_off < block_size) { - /* - * less than block_size: - * the case of incomplete (head or tail), - * or compound block - */ - size_t copied = 0; - /* - * populate the pool with a new block - */ - blocks[*blocks_allocated] = data_alloc_block(this, - local, - block_size); - if (!blocks[*blocks_allocated]) - return -ENOMEM; - memset(blocks[*blocks_allocated], 0, off_in_head); - /* - * fill the block with vec components - */ - do { - size_t to_copy; - - to_copy = vec[vecn].iov_len - vec_off; - if (to_copy > block_size - off_in_head) - to_copy = block_size - off_in_head; - - memcpy(blocks[*blocks_allocated] + off_in_head + copied, - vec[vecn].iov_base + vec_off, - to_copy); - - copied += to_copy; - to_process -= to_copy; - - vec_off += to_copy; - if (vec_off == vec[vecn].iov_len) { - /* finished with this vecn */ - vec_off = 0; - vecn++; - } - } while (copied < (block_size - off_in_head) && to_process > 0); - /* - * update avec - */ - avec[avecn].iov_len = off_in_head + copied; - avec[avecn].iov_base = blocks[*blocks_allocated]; - - (*blocks_allocated)++; - off_in_head = 0; - } else { - /* - * the rest of the current vec component - * is not less than block_size, so reuse - * the memory buffer of the component. - */ - size_t to_reuse; - to_reuse = (to_process > block_size ? - block_size : - to_process); - avec[avecn].iov_len = to_reuse; - avec[avecn].iov_base = vec[vecn].iov_base + vec_off; - - vec_off += to_reuse; - if (vec_off == vec[vecn].iov_len) { - /* finished with this vecn */ - vec_off = 0; - vecn++; - } - to_process -= to_reuse; - } - avecn++; - } - check_iovecs(vec, count, avec, avecn, conf->off_in_head); - return 0; + int vecn = 0; /* number of the current component in vec */ + int avecn = 0; /* number of the current component in avec */ + off_t vec_off = 0; /* offset in the current vec component, + * i.e. the number of bytes have already + * been copied */ + int32_t block_size = get_atom_size(object); + size_t to_process; /* number of vec's bytes to copy and(or) re-use */ + int32_t off_in_head = conf->off_in_head; + + to_process = iov_length(vec, count); + + while (to_process > 0) { + if (off_in_head || vec[vecn].iov_len - vec_off < block_size) { + /* + * less than block_size: + * the case of incomplete (head or tail), + * or compound block + */ + size_t copied = 0; + /* + * populate the pool with a new block + */ + blocks[*blocks_allocated] = data_alloc_block(this, local, + block_size); + if (!blocks[*blocks_allocated]) + return -ENOMEM; + memset(blocks[*blocks_allocated], 0, off_in_head); + /* + * fill the block with vec components + */ + do { + size_t to_copy; + + to_copy = vec[vecn].iov_len - vec_off; + if (to_copy > block_size - off_in_head) + to_copy = block_size - off_in_head; + + memcpy(blocks[*blocks_allocated] + off_in_head + copied, + vec[vecn].iov_base + vec_off, to_copy); + + copied += to_copy; + to_process -= to_copy; + + vec_off += to_copy; + if (vec_off == vec[vecn].iov_len) { + /* finished with this vecn */ + vec_off = 0; + vecn++; + } + } while (copied < (block_size - off_in_head) && to_process > 0); + /* + * update avec + */ + avec[avecn].iov_len = off_in_head + copied; + avec[avecn].iov_base = blocks[*blocks_allocated]; + + (*blocks_allocated)++; + off_in_head = 0; + } else { + /* + * the rest of the current vec component + * is not less than block_size, so reuse + * the memory buffer of the component. + */ + size_t to_reuse; + to_reuse = (to_process > block_size ? block_size : to_process); + avec[avecn].iov_len = to_reuse; + avec[avecn].iov_base = vec[vecn].iov_base + vec_off; + + vec_off += to_reuse; + if (vec_off == vec[vecn].iov_len) { + /* finished with this vecn */ + vec_off = 0; + vecn++; + } + to_process -= to_reuse; + } + avecn++; + } + check_iovecs(vec, count, avec, avecn, conf->off_in_head); + return 0; } /* * allocate and setup aligned vector for data submission * Pre-condition: @conf is set. */ -int32_t set_config_avec_data(xlator_t *this, - crypt_local_t *local, - struct avec_config *conf, - struct object_cipher_info *object, - struct iovec *vec, - int32_t vec_count) +int32_t +set_config_avec_data(xlator_t *this, crypt_local_t *local, + struct avec_config *conf, + struct object_cipher_info *object, struct iovec *vec, + int32_t vec_count) { - int32_t ret = ENOMEM; - struct iovec *avec; - char **pool; - uint32_t blocks_in_pool = 0; - - conf->type = DATA_ATOM; - - avec = GF_CALLOC(conf->acount, sizeof(*avec), gf_crypt_mt_iovec); - if (!avec) - return ret; - pool = GF_CALLOC(conf->acount, sizeof(*pool), gf_crypt_mt_char); - if (!pool) { - GF_FREE(avec); - return ret; - } - if (!vec) { - /* - * degenerated case: no data - */ - pool[0] = data_alloc_block(this, local, get_atom_size(object)); - if (!pool[0]) - goto free; - blocks_in_pool = 1; - avec->iov_base = pool[0]; - avec->iov_len = conf->off_in_tail; - } - else { - ret = align_iov_by_atoms(this, local, object, vec, vec_count, - avec, pool, &blocks_in_pool, conf); - if (ret) - goto free; - } - conf->avec = avec; - conf->pool = pool; - conf->blocks_in_pool = blocks_in_pool; - return 0; - free: - GF_FREE(avec); - GF_FREE(pool); - return ret; + int32_t ret = ENOMEM; + struct iovec *avec; + char **pool; + uint32_t blocks_in_pool = 0; + + conf->type = DATA_ATOM; + + avec = GF_CALLOC(conf->acount, sizeof(*avec), gf_crypt_mt_iovec); + if (!avec) + return ret; + pool = GF_CALLOC(conf->acount, sizeof(*pool), gf_crypt_mt_char); + if (!pool) { + GF_FREE(avec); + return ret; + } + if (!vec) { + /* + * degenerated case: no data + */ + pool[0] = data_alloc_block(this, local, get_atom_size(object)); + if (!pool[0]) + goto free; + blocks_in_pool = 1; + avec->iov_base = pool[0]; + avec->iov_len = conf->off_in_tail; + } else { + ret = align_iov_by_atoms(this, local, object, vec, vec_count, avec, + pool, &blocks_in_pool, conf); + if (ret) + goto free; + } + conf->avec = avec; + conf->pool = pool; + conf->blocks_in_pool = blocks_in_pool; + return 0; +free: + GF_FREE(avec); + GF_FREE(pool); + return ret; } /* * allocate and setup aligned vector for hole submission */ -int32_t set_config_avec_hole(xlator_t *this, - crypt_local_t *local, - struct avec_config *conf, - struct object_cipher_info *object, - glusterfs_fop_t fop) +int32_t +set_config_avec_hole(xlator_t *this, crypt_local_t *local, + struct avec_config *conf, + struct object_cipher_info *object, glusterfs_fop_t fop) { - uint32_t i, idx; - struct iovec *avec; - char **pool; - uint32_t num_blocks; - uint32_t blocks_in_pool = 0; - - conf->type = HOLE_ATOM; - - num_blocks = conf->acount - - (conf->nr_full_blocks ? conf->nr_full_blocks - 1 : 0); - - switch (fop) { - case GF_FOP_WRITE: - /* - * hole goes before data - */ - if (num_blocks == 1 && conf->off_in_tail != 0) - /* - * we won't submit a hole which fits into - * a data atom: this part of hole will be - * submitted with data write - */ - return 0; - break; - case GF_FOP_FTRUNCATE: - /* - * expanding truncate, hole goes after data, - * and will be submitted in any case. - */ - break; - default: - gf_log("crypt", GF_LOG_WARNING, - "bad file operation %d", fop); - return 0; - } - avec = GF_CALLOC(num_blocks, sizeof(*avec), gf_crypt_mt_iovec); - if (!avec) - return ENOMEM; - pool = GF_CALLOC(num_blocks, sizeof(*pool), gf_crypt_mt_char); - if (!pool) { - GF_FREE(avec); - return ENOMEM; - } - for (i = 0; i < num_blocks; i++) { - pool[i] = data_alloc_block(this, local, get_atom_size(object)); - if (pool[i] == NULL) - goto free; - blocks_in_pool++; - } - if (has_head_block(conf)) { - /* set head block */ - idx = 0; - avec[idx].iov_base = pool[idx]; - avec[idx].iov_len = get_atom_size(object); - memset(avec[idx].iov_base + conf->off_in_head, - 0, - get_atom_size(object) - conf->off_in_head); - } - if (has_tail_block(conf)) { - /* set tail block */ - idx = num_blocks - 1; - avec[idx].iov_base = pool[idx]; - avec[idx].iov_len = get_atom_size(object); - memset(avec[idx].iov_base, 0, conf->off_in_tail); - } - if (has_full_blocks(conf)) { - /* set full block */ - idx = conf->off_in_head ? 1 : 0; - avec[idx].iov_base = pool[idx]; - avec[idx].iov_len = get_atom_size(object); - /* - * since we re-use the buffer, - * zeroes will be set every time - * before encryption, see submit_full() - */ - } - conf->avec = avec; - conf->pool = pool; - conf->blocks_in_pool = blocks_in_pool; - return 0; - free: - GF_FREE(avec); - GF_FREE(pool); - return ENOMEM; + uint32_t i, idx; + struct iovec *avec; + char **pool; + uint32_t num_blocks; + uint32_t blocks_in_pool = 0; + + conf->type = HOLE_ATOM; + + num_blocks = conf->acount - + (conf->nr_full_blocks ? conf->nr_full_blocks - 1 : 0); + + switch (fop) { + case GF_FOP_WRITE: + /* + * hole goes before data + */ + if (num_blocks == 1 && conf->off_in_tail != 0) + /* + * we won't submit a hole which fits into + * a data atom: this part of hole will be + * submitted with data write + */ + return 0; + break; + case GF_FOP_FTRUNCATE: + /* + * expanding truncate, hole goes after data, + * and will be submitted in any case. + */ + break; + default: + gf_log("crypt", GF_LOG_WARNING, "bad file operation %d", fop); + return 0; + } + avec = GF_CALLOC(num_blocks, sizeof(*avec), gf_crypt_mt_iovec); + if (!avec) + return ENOMEM; + pool = GF_CALLOC(num_blocks, sizeof(*pool), gf_crypt_mt_char); + if (!pool) { + GF_FREE(avec); + return ENOMEM; + } + for (i = 0; i < num_blocks; i++) { + pool[i] = data_alloc_block(this, local, get_atom_size(object)); + if (pool[i] == NULL) + goto free; + blocks_in_pool++; + } + if (has_head_block(conf)) { + /* set head block */ + idx = 0; + avec[idx].iov_base = pool[idx]; + avec[idx].iov_len = get_atom_size(object); + memset(avec[idx].iov_base + conf->off_in_head, 0, + get_atom_size(object) - conf->off_in_head); + } + if (has_tail_block(conf)) { + /* set tail block */ + idx = num_blocks - 1; + avec[idx].iov_base = pool[idx]; + avec[idx].iov_len = get_atom_size(object); + memset(avec[idx].iov_base, 0, conf->off_in_tail); + } + if (has_full_blocks(conf)) { + /* set full block */ + idx = conf->off_in_head ? 1 : 0; + avec[idx].iov_base = pool[idx]; + avec[idx].iov_len = get_atom_size(object); + /* + * since we re-use the buffer, + * zeroes will be set every time + * before encryption, see submit_full() + */ + } + conf->avec = avec; + conf->pool = pool; + conf->blocks_in_pool = blocks_in_pool; + return 0; +free: + GF_FREE(avec); + GF_FREE(pool); + return ENOMEM; } /* A helper for setting up config of partial atoms (which @@ -617,140 +575,133 @@ int32_t set_config_avec_hole(xlator_t *this, * @conf contains setup, which is enough for correct calculation * of has_tail_block(), ->get_offset(). */ -void set_gap_at_end(call_frame_t *frame, struct object_cipher_info *object, - struct avec_config *conf, atom_data_type dtype) +void +set_gap_at_end(call_frame_t *frame, struct object_cipher_info *object, + struct avec_config *conf, atom_data_type dtype) { - uint32_t to_block; - crypt_local_t *local = frame->local; - uint64_t old_file_size = local->old_file_size; - struct rmw_atom *partial = atom_by_types(dtype, - has_tail_block(conf) ? - TAIL_ATOM : HEAD_ATOM); - - if (old_file_size <= partial->offset_at(frame, object)) - to_block = 0; - else { - to_block = old_file_size - partial->offset_at(frame, object); - if (to_block > get_atom_size(object)) - to_block = get_atom_size(object); - } - if (to_block > conf->off_in_tail) - conf->gap_in_tail = to_block - conf->off_in_tail; - else - /* - * nothing to uptodate - */ - conf->gap_in_tail = 0; + uint32_t to_block; + crypt_local_t *local = frame->local; + uint64_t old_file_size = local->old_file_size; + struct rmw_atom *partial = atom_by_types( + dtype, has_tail_block(conf) ? TAIL_ATOM : HEAD_ATOM); + + if (old_file_size <= partial->offset_at(frame, object)) + to_block = 0; + else { + to_block = old_file_size - partial->offset_at(frame, object); + if (to_block > get_atom_size(object)) + to_block = get_atom_size(object); + } + if (to_block > conf->off_in_tail) + conf->gap_in_tail = to_block - conf->off_in_tail; + else + /* + * nothing to uptodate + */ + conf->gap_in_tail = 0; } /* * fill struct avec_config with offsets layouts */ -void set_config_offsets(call_frame_t *frame, - xlator_t *this, - uint64_t offset, - uint64_t count, - atom_data_type dtype, - int32_t set_gap) +void +set_config_offsets(call_frame_t *frame, xlator_t *this, uint64_t offset, + uint64_t count, atom_data_type dtype, int32_t set_gap) { - crypt_local_t *local; - struct object_cipher_info *object; - struct avec_config *conf; - uint32_t resid; - - uint32_t atom_size; - uint32_t atom_bits; - - size_t orig_size; - off_t orig_offset; - size_t expanded_size; - off_t aligned_offset; - - uint32_t off_in_head = 0; - uint32_t off_in_tail = 0; - uint32_t nr_full_blocks; - int32_t size_full_blocks; - - uint32_t acount; /* number of aligned components to write. - * The same as number of occupied logical - * blocks (atoms) - */ - local = frame->local; - object = &local->info->cinfo; - conf = (dtype == DATA_ATOM ? - get_data_conf(frame) : get_hole_conf(frame)); - - orig_offset = offset; - orig_size = count; - - atom_size = get_atom_size(object); - atom_bits = get_atom_bits(object); - - /* - * Round-down the start, - * round-up the end. - */ - resid = offset & (uint64_t)(atom_size - 1); - - if (resid) - off_in_head = resid; - aligned_offset = offset - off_in_head; - expanded_size = orig_size + off_in_head; - - /* calculate tail, - expand size forward */ - resid = (offset + orig_size) & (uint64_t)(atom_size - 1); - - if (resid) { - off_in_tail = resid; - expanded_size += (atom_size - off_in_tail); - } - /* - * calculate number of occupied blocks - */ - acount = expanded_size >> atom_bits; - /* - * calculate number of full blocks - */ - size_full_blocks = expanded_size; - if (off_in_head) - size_full_blocks -= atom_size; - if (off_in_tail && size_full_blocks > 0) - size_full_blocks -= atom_size; - nr_full_blocks = size_full_blocks >> atom_bits; - - conf->atom_size = atom_size; - conf->orig_size = orig_size; - conf->orig_offset = orig_offset; - conf->expanded_size = expanded_size; - conf->aligned_offset = aligned_offset; - - conf->off_in_head = off_in_head; - conf->off_in_tail = off_in_tail; - conf->nr_full_blocks = nr_full_blocks; - conf->acount = acount; - /* - * Finally, calculate precise amount of - * "extra-bytes" that should be uptodated - * at the end. - * Only if RMW is expected. - */ - if (off_in_tail && set_gap) - set_gap_at_end(frame, object, conf, dtype); + crypt_local_t *local; + struct object_cipher_info *object; + struct avec_config *conf; + uint32_t resid; + + uint32_t atom_size; + uint32_t atom_bits; + + size_t orig_size; + off_t orig_offset; + size_t expanded_size; + off_t aligned_offset; + + uint32_t off_in_head = 0; + uint32_t off_in_tail = 0; + uint32_t nr_full_blocks; + int32_t size_full_blocks; + + uint32_t acount; /* number of aligned components to write. + * The same as number of occupied logical + * blocks (atoms) + */ + local = frame->local; + object = &local->info->cinfo; + conf = (dtype == DATA_ATOM ? get_data_conf(frame) : get_hole_conf(frame)); + + orig_offset = offset; + orig_size = count; + + atom_size = get_atom_size(object); + atom_bits = get_atom_bits(object); + + /* + * Round-down the start, + * round-up the end. + */ + resid = offset & (uint64_t)(atom_size - 1); + + if (resid) + off_in_head = resid; + aligned_offset = offset - off_in_head; + expanded_size = orig_size + off_in_head; + + /* calculate tail, + expand size forward */ + resid = (offset + orig_size) & (uint64_t)(atom_size - 1); + + if (resid) { + off_in_tail = resid; + expanded_size += (atom_size - off_in_tail); + } + /* + * calculate number of occupied blocks + */ + acount = expanded_size >> atom_bits; + /* + * calculate number of full blocks + */ + size_full_blocks = expanded_size; + if (off_in_head) + size_full_blocks -= atom_size; + if (off_in_tail && size_full_blocks > 0) + size_full_blocks -= atom_size; + nr_full_blocks = size_full_blocks >> atom_bits; + + conf->atom_size = atom_size; + conf->orig_size = orig_size; + conf->orig_offset = orig_offset; + conf->expanded_size = expanded_size; + conf->aligned_offset = aligned_offset; + + conf->off_in_head = off_in_head; + conf->off_in_tail = off_in_tail; + conf->nr_full_blocks = nr_full_blocks; + conf->acount = acount; + /* + * Finally, calculate precise amount of + * "extra-bytes" that should be uptodated + * at the end. + * Only if RMW is expected. + */ + if (off_in_tail && set_gap) + set_gap_at_end(frame, object, conf, dtype); } struct data_cipher_alg data_cipher_algs[LAST_CIPHER_ALG][LAST_CIPHER_MODE] = { - [AES_CIPHER_ALG][XTS_CIPHER_MODE] = - { .atomic = _gf_true, - .should_pad = _gf_true, - .blkbits = AES_BLOCK_BITS, - .init = aes_xts_init, - .set_private = set_private_aes_xts, - .check_key = check_key_aes_xts, - .set_iv = set_iv_aes_xts, - .encrypt = encrypt_aes_xts - } -}; + [AES_CIPHER_ALG][XTS_CIPHER_MODE] = {.atomic = _gf_true, + .should_pad = _gf_true, + .blkbits = AES_BLOCK_BITS, + .init = aes_xts_init, + .set_private = set_private_aes_xts, + .check_key = check_key_aes_xts, + .set_iv = set_iv_aes_xts, + .encrypt = encrypt_aes_xts}}; /* Local variables: |