#include <linux/crypto.h>
#include <linux/workqueue.h>
#include <asm/atomic.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
#include <asm/page.h>
#include "dm.h"
static kmem_cache_t *_crypt_io_pool;
-/*
- * Mempool alloc and free functions for the page
- */
-static void *mempool_alloc_page(int gfp_mask, void *data)
-{
- return alloc_page(gfp_mask);
-}
-
-static void mempool_free_page(void *page, void *data)
-{
- __free_page(page);
-}
-
-
/*
* Different IV generation algorithms:
*
}
/* Hash the cipher key with the given hash algorithm */
- hash_tfm = crypto_alloc_tfm(opts, 0);
+ hash_tfm = crypto_alloc_tfm(opts, CRYPTO_TFM_REQ_MAY_SLEEP);
if (hash_tfm == NULL) {
ti->error = PFX "Error initializing ESSIV hash";
return -EINVAL;
return -ENOMEM;
}
- sg.page = virt_to_page(cc->key);
- sg.offset = offset_in_page(cc->key);
- sg.length = cc->key_size;
+ sg_set_buf(&sg, cc->key, cc->key_size);
crypto_digest_digest(hash_tfm, &sg, 1, salt);
crypto_free_tfm(hash_tfm);
/* Setup the essiv_tfm with the given salt */
essiv_tfm = crypto_alloc_tfm(crypto_tfm_alg_name(cc->tfm),
- CRYPTO_TFM_MODE_ECB);
+ CRYPTO_TFM_MODE_ECB |
+ CRYPTO_TFM_REQ_MAY_SLEEP);
if (essiv_tfm == NULL) {
ti->error = PFX "Error allocating crypto tfm for ESSIV";
kfree(salt);
static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
{
- struct scatterlist sg = { NULL, };
+ struct scatterlist sg;
memset(iv, 0, cc->iv_size);
*(u64 *)iv = cpu_to_le64(sector);
- sg.page = virt_to_page(iv);
- sg.offset = offset_in_page(iv);
- sg.length = cc->iv_size;
+ sg_set_buf(&sg, iv, cc->iv_size);
crypto_cipher_encrypt((struct crypto_tfm *)cc->iv_gen_private,
&sg, &sg, cc->iv_size);
};
-static inline int
+static int
crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out,
struct scatterlist *in, unsigned int length,
int write, sector_t sector)
{
struct bio *bio;
unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
- int gfp_mask = GFP_NOIO | __GFP_HIGHMEM;
- unsigned long flags = current->flags;
+ gfp_t gfp_mask = GFP_NOIO | __GFP_HIGHMEM;
unsigned int i;
/*
- * Tell VM to act less aggressively and fail earlier.
- * This is not necessary but increases throughput.
+ * Use __GFP_NOMEMALLOC to tell the VM to act less aggressively and
+ * to fail earlier. This is not necessary but increases throughput.
* FIXME: Is this really intelligent?
*/
- current->flags &= ~PF_MEMALLOC;
-
if (base_bio)
- bio = bio_clone(base_bio, GFP_NOIO);
+ bio = bio_clone(base_bio, GFP_NOIO|__GFP_NOMEMALLOC);
else
- bio = bio_alloc(GFP_NOIO, nr_iovecs);
- if (!bio) {
- if (flags & PF_MEMALLOC)
- current->flags |= PF_MEMALLOC;
+ bio = bio_alloc(GFP_NOIO|__GFP_NOMEMALLOC, nr_iovecs);
+ if (!bio)
return NULL;
- }
/* if the last bio was not complete, continue where that one ended */
bio->bi_idx = *bio_vec_idx;
size -= bv->bv_len;
}
- if (flags & PF_MEMALLOC)
- current->flags |= PF_MEMALLOC;
-
if (!bio->bi_size) {
bio_put(bio);
return NULL;
char *ivopts;
unsigned int crypto_flags;
unsigned int key_size;
+ unsigned long long tmpll;
if (argc != 5) {
ti->error = PFX "Not enough arguments";
goto bad1;
}
- tfm = crypto_alloc_tfm(cipher, crypto_flags);
+ tfm = crypto_alloc_tfm(cipher, crypto_flags | CRYPTO_TFM_REQ_MAY_SLEEP);
if (!tfm) {
ti->error = PFX "Error allocating crypto tfm";
goto bad1;
}
}
- cc->io_pool = mempool_create(MIN_IOS, mempool_alloc_slab,
- mempool_free_slab, _crypt_io_pool);
+ cc->io_pool = mempool_create_slab_pool(MIN_IOS, _crypt_io_pool);
if (!cc->io_pool) {
ti->error = PFX "Cannot allocate crypt io mempool";
goto bad3;
}
- cc->page_pool = mempool_create(MIN_POOL_PAGES, mempool_alloc_page,
- mempool_free_page, NULL);
+ cc->page_pool = mempool_create_page_pool(MIN_POOL_PAGES, 0);
if (!cc->page_pool) {
ti->error = PFX "Cannot allocate page mempool";
goto bad4;
goto bad5;
}
- if (sscanf(argv[2], SECTOR_FORMAT, &cc->iv_offset) != 1) {
+ if (sscanf(argv[2], "%llu", &tmpll) != 1) {
ti->error = PFX "Invalid iv_offset sector";
goto bad5;
}
+ cc->iv_offset = tmpll;
- if (sscanf(argv[4], SECTOR_FORMAT, &cc->start) != 1) {
+ if (sscanf(argv[4], "%llu", &tmpll) != 1) {
ti->error = PFX "Invalid device sector";
goto bad5;
}
+ cc->start = tmpll;
if (dm_get_device(ti, argv[3], cc->start, ti->len,
dm_table_get_mode(ti->table), &cc->dev)) {
bad2:
crypto_free_tfm(tfm);
bad1:
+ /* Must zero key material before freeing */
+ memset(cc, 0, sizeof(*cc) + cc->key_size * sizeof(u8));
kfree(cc);
return -EINVAL;
}
mempool_destroy(cc->page_pool);
mempool_destroy(cc->io_pool);
- if (cc->iv_mode)
- kfree(cc->iv_mode);
+ kfree(cc->iv_mode);
if (cc->iv_gen_ops && cc->iv_gen_ops->dtr)
cc->iv_gen_ops->dtr(cc);
crypto_free_tfm(cc->tfm);
dm_put_device(ti, cc->dev);
+
+ /* Must zero key material before freeing */
+ memset(cc, 0, sizeof(*cc) + cc->key_size * sizeof(u8));
kfree(cc);
}
char *result, unsigned int maxlen)
{
struct crypt_config *cc = (struct crypt_config *) ti->private;
- char buffer[32];
const char *cipher;
const char *chainmode = NULL;
unsigned int sz = 0;
result[sz++] = '-';
}
- format_dev_t(buffer, cc->dev->bdev->bd_dev);
- DMEMIT(" " SECTOR_FORMAT " %s " SECTOR_FORMAT,
- cc->iv_offset, buffer, cc->start);
+ DMEMIT(" %llu %s %llu", (unsigned long long)cc->iv_offset,
+ cc->dev->name, (unsigned long long)cc->start);
break;
}
return 0;