aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/dm-crypt.c63
1 files changed, 39 insertions, 24 deletions
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 44e1aa30e3f6..2da9b9536afb 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -55,6 +55,11 @@ struct dm_crypt_io {
55 sector_t sector; 55 sector_t sector;
56}; 56};
57 57
58struct dm_crypt_request {
59 struct scatterlist sg_in;
60 struct scatterlist sg_out;
61};
62
58struct crypt_config; 63struct crypt_config;
59 64
60struct crypt_iv_operations { 65struct crypt_iv_operations {
@@ -339,6 +344,39 @@ static void crypt_convert_init(struct crypt_config *cc,
339 ctx->sector = sector + cc->iv_offset; 344 ctx->sector = sector + cc->iv_offset;
340} 345}
341 346
347static int crypt_convert_block(struct crypt_config *cc,
348 struct convert_context *ctx)
349{
350 struct bio_vec *bv_in = bio_iovec_idx(ctx->bio_in, ctx->idx_in);
351 struct bio_vec *bv_out = bio_iovec_idx(ctx->bio_out, ctx->idx_out);
352 struct dm_crypt_request dmreq;
353
354 sg_init_table(&dmreq.sg_in, 1);
355 sg_set_page(&dmreq.sg_in, bv_in->bv_page, 1 << SECTOR_SHIFT,
356 bv_in->bv_offset + ctx->offset_in);
357
358 sg_init_table(&dmreq.sg_out, 1);
359 sg_set_page(&dmreq.sg_out, bv_out->bv_page, 1 << SECTOR_SHIFT,
360 bv_out->bv_offset + ctx->offset_out);
361
362 ctx->offset_in += 1 << SECTOR_SHIFT;
363 if (ctx->offset_in >= bv_in->bv_len) {
364 ctx->offset_in = 0;
365 ctx->idx_in++;
366 }
367
368 ctx->offset_out += 1 << SECTOR_SHIFT;
369 if (ctx->offset_out >= bv_out->bv_len) {
370 ctx->offset_out = 0;
371 ctx->idx_out++;
372 }
373
374 return crypt_convert_scatterlist(cc, &dmreq.sg_out, &dmreq.sg_in,
375 dmreq.sg_in.length,
376 bio_data_dir(ctx->bio_in) == WRITE,
377 ctx->sector);
378}
379
342/* 380/*
343 * Encrypt / decrypt data from one bio to another one (can be the same one) 381 * Encrypt / decrypt data from one bio to another one (can be the same one)
344 */ 382 */
@@ -349,30 +387,7 @@ static int crypt_convert(struct crypt_config *cc,
349 387
350 while(ctx->idx_in < ctx->bio_in->bi_vcnt && 388 while(ctx->idx_in < ctx->bio_in->bi_vcnt &&
351 ctx->idx_out < ctx->bio_out->bi_vcnt) { 389 ctx->idx_out < ctx->bio_out->bi_vcnt) {
352 struct bio_vec *bv_in = bio_iovec_idx(ctx->bio_in, ctx->idx_in); 390 r = crypt_convert_block(cc, ctx);
353 struct bio_vec *bv_out = bio_iovec_idx(ctx->bio_out, ctx->idx_out);
354 struct scatterlist sg_in, sg_out;
355
356 sg_init_table(&sg_in, 1);
357 sg_set_page(&sg_in, bv_in->bv_page, 1 << SECTOR_SHIFT, bv_in->bv_offset + ctx->offset_in);
358
359 sg_init_table(&sg_out, 1);
360 sg_set_page(&sg_out, bv_out->bv_page, 1 << SECTOR_SHIFT, bv_out->bv_offset + ctx->offset_out);
361
362 ctx->offset_in += sg_in.length;
363 if (ctx->offset_in >= bv_in->bv_len) {
364 ctx->offset_in = 0;
365 ctx->idx_in++;
366 }
367
368 ctx->offset_out += sg_out.length;
369 if (ctx->offset_out >= bv_out->bv_len) {
370 ctx->offset_out = 0;
371 ctx->idx_out++;
372 }
373
374 r = crypt_convert_scatterlist(cc, &sg_out, &sg_in, sg_in.length,
375 bio_data_dir(ctx->bio_in) == WRITE, ctx->sector);
376 if (r < 0) 391 if (r < 0)
377 break; 392 break;
378 393