Improve performance when AES-NI (and most likely other crypto accelerators) is
available by moving to the ablkcipher crypto API. The improvement is more apparent on faster storage devices. There's no noticeable change when hardware crypto is not available. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQIcBAABCgAGBQJRjJFjAAoJENaSAD2qAscKuRgQAJkefyLPNBb4plXr3R+zJ1aM jkcqkUJWamCxlmqHg/n9LmlxpSZiiWSWJM8iiq8zQhPE0PVXVOVhqvzogT1xwv75 xfT9xTuRi1v7UFaSGHtj3WoO2nscQ0pjZW/0CHgd/PZjz9y0iJ/l6ueoWCOz5L2i 3oJvx/W407qM+MSogWKx79i1B2jILdBdQH/7PZ+UJS3jWEo3rMWBbfCwbYhd4pUG oVc+qFglNs+3HLdHVUmHPCerCL9qYAJIJmDrvupSOQ6DwdFaV8IysTgSEdFtLcfC 8Z6DUOPzXnvA/+y+NCCCUxg1CrkgYkNrefLKAq18atFu63zIZIHZyJBTJ5Q6vXVF o1H8UcIOg/liGa6lXGf5b4ENNKvB0qMYQgiSrL0/FVVima4zGqUWkQLno4kQl1zx FHB5imQ7F/EMcow/nTN3YQYC3N/iYIFAIRxf35SiGGsNhO2sEyIqYlRSyq2MNrRl pLWNbhnRuhBUqcbqZDxq1oZ7624Ui4jnHHx7rl6Y3gfm8Xa1ZmQeY6rOadSZaRd7 +ZqFZi1jiHz1c0tVUO/3DsqABIhbr9Ee03vracN8bVTGV0ZmO0qneugFB9esoeDf UnrU0Im8ilHu3OHAyc+UkRZuzThL9bLZEivwICQ+JDUJ1zsLYSQZEaGIt8hA0iDy 8Bu3gtfX2WxD4ak/AkFv =3EhP -----END PGP SIGNATURE----- Merge tag 'ecryptfs-3.10-rc1-ablkcipher' of git://git.kernel.org/pub/scm/linux/kernel/git/tyhicks/ecryptfs Pull eCryptfs update from Tyler Hicks: "Improve performance when AES-NI (and most likely other crypto accelerators) is available by moving to the ablkcipher crypto API. The improvement is more apparent on faster storage devices. There's no noticeable change when hardware crypto is not available" * tag 'ecryptfs-3.10-rc1-ablkcipher' of git://git.kernel.org/pub/scm/linux/kernel/git/tyhicks/ecryptfs: eCryptfs: Use the ablkcipher crypto API
This commit is contained in:
commit
6fad8d02ef
|
@ -243,7 +243,7 @@ void ecryptfs_destroy_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat)
|
||||||
struct ecryptfs_key_sig *key_sig, *key_sig_tmp;
|
struct ecryptfs_key_sig *key_sig, *key_sig_tmp;
|
||||||
|
|
||||||
if (crypt_stat->tfm)
|
if (crypt_stat->tfm)
|
||||||
crypto_free_blkcipher(crypt_stat->tfm);
|
crypto_free_ablkcipher(crypt_stat->tfm);
|
||||||
if (crypt_stat->hash_tfm)
|
if (crypt_stat->hash_tfm)
|
||||||
crypto_free_hash(crypt_stat->hash_tfm);
|
crypto_free_hash(crypt_stat->hash_tfm);
|
||||||
list_for_each_entry_safe(key_sig, key_sig_tmp,
|
list_for_each_entry_safe(key_sig, key_sig_tmp,
|
||||||
|
@ -319,6 +319,22 @@ int virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg,
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct extent_crypt_result {
|
||||||
|
struct completion completion;
|
||||||
|
int rc;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void extent_crypt_complete(struct crypto_async_request *req, int rc)
|
||||||
|
{
|
||||||
|
struct extent_crypt_result *ecr = req->data;
|
||||||
|
|
||||||
|
if (rc == -EINPROGRESS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ecr->rc = rc;
|
||||||
|
complete(&ecr->completion);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* encrypt_scatterlist
|
* encrypt_scatterlist
|
||||||
* @crypt_stat: Pointer to the crypt_stat struct to initialize.
|
* @crypt_stat: Pointer to the crypt_stat struct to initialize.
|
||||||
|
@ -334,11 +350,8 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat,
|
||||||
struct scatterlist *src_sg, int size,
|
struct scatterlist *src_sg, int size,
|
||||||
unsigned char *iv)
|
unsigned char *iv)
|
||||||
{
|
{
|
||||||
struct blkcipher_desc desc = {
|
struct ablkcipher_request *req = NULL;
|
||||||
.tfm = crypt_stat->tfm,
|
struct extent_crypt_result ecr;
|
||||||
.info = iv,
|
|
||||||
.flags = CRYPTO_TFM_REQ_MAY_SLEEP
|
|
||||||
};
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
BUG_ON(!crypt_stat || !crypt_stat->tfm
|
BUG_ON(!crypt_stat || !crypt_stat->tfm
|
||||||
|
@ -349,24 +362,47 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat,
|
||||||
ecryptfs_dump_hex(crypt_stat->key,
|
ecryptfs_dump_hex(crypt_stat->key,
|
||||||
crypt_stat->key_size);
|
crypt_stat->key_size);
|
||||||
}
|
}
|
||||||
/* Consider doing this once, when the file is opened */
|
|
||||||
|
init_completion(&ecr.completion);
|
||||||
|
|
||||||
mutex_lock(&crypt_stat->cs_tfm_mutex);
|
mutex_lock(&crypt_stat->cs_tfm_mutex);
|
||||||
if (!(crypt_stat->flags & ECRYPTFS_KEY_SET)) {
|
req = ablkcipher_request_alloc(crypt_stat->tfm, GFP_NOFS);
|
||||||
rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key,
|
if (!req) {
|
||||||
crypt_stat->key_size);
|
|
||||||
crypt_stat->flags |= ECRYPTFS_KEY_SET;
|
|
||||||
}
|
|
||||||
if (rc) {
|
|
||||||
ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n",
|
|
||||||
rc);
|
|
||||||
mutex_unlock(&crypt_stat->cs_tfm_mutex);
|
mutex_unlock(&crypt_stat->cs_tfm_mutex);
|
||||||
rc = -EINVAL;
|
rc = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes.\n", size);
|
|
||||||
crypto_blkcipher_encrypt_iv(&desc, dest_sg, src_sg, size);
|
ablkcipher_request_set_callback(req,
|
||||||
|
CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
|
||||||
|
extent_crypt_complete, &ecr);
|
||||||
|
/* Consider doing this once, when the file is opened */
|
||||||
|
if (!(crypt_stat->flags & ECRYPTFS_KEY_SET)) {
|
||||||
|
rc = crypto_ablkcipher_setkey(crypt_stat->tfm, crypt_stat->key,
|
||||||
|
crypt_stat->key_size);
|
||||||
|
if (rc) {
|
||||||
|
ecryptfs_printk(KERN_ERR,
|
||||||
|
"Error setting key; rc = [%d]\n",
|
||||||
|
rc);
|
||||||
|
mutex_unlock(&crypt_stat->cs_tfm_mutex);
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
crypt_stat->flags |= ECRYPTFS_KEY_SET;
|
||||||
|
}
|
||||||
mutex_unlock(&crypt_stat->cs_tfm_mutex);
|
mutex_unlock(&crypt_stat->cs_tfm_mutex);
|
||||||
|
ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes.\n", size);
|
||||||
|
ablkcipher_request_set_crypt(req, src_sg, dest_sg, size, iv);
|
||||||
|
rc = crypto_ablkcipher_encrypt(req);
|
||||||
|
if (rc == -EINPROGRESS || rc == -EBUSY) {
|
||||||
|
struct extent_crypt_result *ecr = req->base.data;
|
||||||
|
|
||||||
|
wait_for_completion(&ecr->completion);
|
||||||
|
rc = ecr->rc;
|
||||||
|
INIT_COMPLETION(ecr->completion);
|
||||||
|
}
|
||||||
out:
|
out:
|
||||||
|
ablkcipher_request_free(req);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -624,35 +660,61 @@ static int decrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat,
|
||||||
struct scatterlist *src_sg, int size,
|
struct scatterlist *src_sg, int size,
|
||||||
unsigned char *iv)
|
unsigned char *iv)
|
||||||
{
|
{
|
||||||
struct blkcipher_desc desc = {
|
struct ablkcipher_request *req = NULL;
|
||||||
.tfm = crypt_stat->tfm,
|
struct extent_crypt_result ecr;
|
||||||
.info = iv,
|
|
||||||
.flags = CRYPTO_TFM_REQ_MAY_SLEEP
|
|
||||||
};
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
/* Consider doing this once, when the file is opened */
|
BUG_ON(!crypt_stat || !crypt_stat->tfm
|
||||||
|
|| !(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED));
|
||||||
|
if (unlikely(ecryptfs_verbosity > 0)) {
|
||||||
|
ecryptfs_printk(KERN_DEBUG, "Key size [%zd]; key:\n",
|
||||||
|
crypt_stat->key_size);
|
||||||
|
ecryptfs_dump_hex(crypt_stat->key,
|
||||||
|
crypt_stat->key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
init_completion(&ecr.completion);
|
||||||
|
|
||||||
mutex_lock(&crypt_stat->cs_tfm_mutex);
|
mutex_lock(&crypt_stat->cs_tfm_mutex);
|
||||||
rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key,
|
req = ablkcipher_request_alloc(crypt_stat->tfm, GFP_NOFS);
|
||||||
crypt_stat->key_size);
|
if (!req) {
|
||||||
if (rc) {
|
|
||||||
ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n",
|
|
||||||
rc);
|
|
||||||
mutex_unlock(&crypt_stat->cs_tfm_mutex);
|
mutex_unlock(&crypt_stat->cs_tfm_mutex);
|
||||||
rc = -EINVAL;
|
rc = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
ecryptfs_printk(KERN_DEBUG, "Decrypting [%d] bytes.\n", size);
|
|
||||||
rc = crypto_blkcipher_decrypt_iv(&desc, dest_sg, src_sg, size);
|
ablkcipher_request_set_callback(req,
|
||||||
|
CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
|
||||||
|
extent_crypt_complete, &ecr);
|
||||||
|
/* Consider doing this once, when the file is opened */
|
||||||
|
if (!(crypt_stat->flags & ECRYPTFS_KEY_SET)) {
|
||||||
|
rc = crypto_ablkcipher_setkey(crypt_stat->tfm, crypt_stat->key,
|
||||||
|
crypt_stat->key_size);
|
||||||
|
if (rc) {
|
||||||
|
ecryptfs_printk(KERN_ERR,
|
||||||
|
"Error setting key; rc = [%d]\n",
|
||||||
|
rc);
|
||||||
|
mutex_unlock(&crypt_stat->cs_tfm_mutex);
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
crypt_stat->flags |= ECRYPTFS_KEY_SET;
|
||||||
|
}
|
||||||
mutex_unlock(&crypt_stat->cs_tfm_mutex);
|
mutex_unlock(&crypt_stat->cs_tfm_mutex);
|
||||||
if (rc) {
|
ecryptfs_printk(KERN_DEBUG, "Decrypting [%d] bytes.\n", size);
|
||||||
ecryptfs_printk(KERN_ERR, "Error decrypting; rc = [%d]\n",
|
ablkcipher_request_set_crypt(req, src_sg, dest_sg, size, iv);
|
||||||
rc);
|
rc = crypto_ablkcipher_decrypt(req);
|
||||||
goto out;
|
if (rc == -EINPROGRESS || rc == -EBUSY) {
|
||||||
|
struct extent_crypt_result *ecr = req->base.data;
|
||||||
|
|
||||||
|
wait_for_completion(&ecr->completion);
|
||||||
|
rc = ecr->rc;
|
||||||
|
INIT_COMPLETION(ecr->completion);
|
||||||
}
|
}
|
||||||
rc = size;
|
|
||||||
out:
|
out:
|
||||||
|
ablkcipher_request_free(req);
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -746,8 +808,7 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat)
|
||||||
crypt_stat->cipher, "cbc");
|
crypt_stat->cipher, "cbc");
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
crypt_stat->tfm = crypto_alloc_blkcipher(full_alg_name, 0,
|
crypt_stat->tfm = crypto_alloc_ablkcipher(full_alg_name, 0, 0);
|
||||||
CRYPTO_ALG_ASYNC);
|
|
||||||
kfree(full_alg_name);
|
kfree(full_alg_name);
|
||||||
if (IS_ERR(crypt_stat->tfm)) {
|
if (IS_ERR(crypt_stat->tfm)) {
|
||||||
rc = PTR_ERR(crypt_stat->tfm);
|
rc = PTR_ERR(crypt_stat->tfm);
|
||||||
|
@ -757,7 +818,7 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat)
|
||||||
crypt_stat->cipher);
|
crypt_stat->cipher);
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
crypto_blkcipher_set_flags(crypt_stat->tfm, CRYPTO_TFM_REQ_WEAK_KEY);
|
crypto_ablkcipher_set_flags(crypt_stat->tfm, CRYPTO_TFM_REQ_WEAK_KEY);
|
||||||
rc = 0;
|
rc = 0;
|
||||||
out_unlock:
|
out_unlock:
|
||||||
mutex_unlock(&crypt_stat->cs_tfm_mutex);
|
mutex_unlock(&crypt_stat->cs_tfm_mutex);
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include <linux/nsproxy.h>
|
#include <linux/nsproxy.h>
|
||||||
#include <linux/backing-dev.h>
|
#include <linux/backing-dev.h>
|
||||||
#include <linux/ecryptfs.h>
|
#include <linux/ecryptfs.h>
|
||||||
|
#include <linux/crypto.h>
|
||||||
|
|
||||||
#define ECRYPTFS_DEFAULT_IV_BYTES 16
|
#define ECRYPTFS_DEFAULT_IV_BYTES 16
|
||||||
#define ECRYPTFS_DEFAULT_EXTENT_SIZE 4096
|
#define ECRYPTFS_DEFAULT_EXTENT_SIZE 4096
|
||||||
|
@ -233,7 +234,7 @@ struct ecryptfs_crypt_stat {
|
||||||
size_t extent_shift;
|
size_t extent_shift;
|
||||||
unsigned int extent_mask;
|
unsigned int extent_mask;
|
||||||
struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
|
struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
|
||||||
struct crypto_blkcipher *tfm;
|
struct crypto_ablkcipher *tfm;
|
||||||
struct crypto_hash *hash_tfm; /* Crypto context for generating
|
struct crypto_hash *hash_tfm; /* Crypto context for generating
|
||||||
* the initialization vectors */
|
* the initialization vectors */
|
||||||
unsigned char cipher[ECRYPTFS_MAX_CIPHER_NAME_SIZE];
|
unsigned char cipher[ECRYPTFS_MAX_CIPHER_NAME_SIZE];
|
||||||
|
|
Loading…
Reference in New Issue