diff options
Diffstat (limited to 'drivers/md/dm-crypt.c')
-rw-r--r-- | drivers/md/dm-crypt.c | 63 |
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 | ||
58 | struct dm_crypt_request { | ||
59 | struct scatterlist sg_in; | ||
60 | struct scatterlist sg_out; | ||
61 | }; | ||
62 | |||
58 | struct crypt_config; | 63 | struct crypt_config; |
59 | 64 | ||
60 | struct crypt_iv_operations { | 65 | struct 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 | ||
347 | static 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 | ||