Skip to content

Commit

Permalink
dm crypt: use io thread for reads only if mempool exhausted
Browse files Browse the repository at this point in the history
If there is enough memory, code can directly submit bio
instead queing this operation in separate thread.

Try to alloc bio clone with GFP_NOWAIT and only if it
fails use separate queue (map function cannot block here).

Signed-off-by: Milan Broz <mbroz@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
  • Loading branch information
Milan Broz authored and kergon committed Jan 13, 2011
1 parent c029772 commit 20c8253
Showing 1 changed file with 23 additions and 14 deletions.
37 changes: 23 additions & 14 deletions drivers/md/dm-crypt.c
Expand Up @@ -787,26 +787,30 @@ static void clone_init(struct dm_crypt_io *io, struct bio *clone)
clone->bi_destructor = dm_crypt_bio_destructor;
}

static void kcryptd_io_read(struct dm_crypt_io *io)
static void kcryptd_unplug(struct crypt_config *cc)
{
blk_unplug(bdev_get_queue(cc->dev->bdev));
}

static int kcryptd_io_read(struct dm_crypt_io *io, gfp_t gfp)
{
struct crypt_config *cc = io->target->private;
struct bio *base_bio = io->base_bio;
struct bio *clone;

crypt_inc_pending(io);

/*
* The block layer might modify the bvec array, so always
* copy the required bvecs because we need the original
* one in order to decrypt the whole bio data *afterwards*.
*/
clone = bio_alloc_bioset(GFP_NOIO, bio_segments(base_bio), cc->bs);
if (unlikely(!clone)) {
io->error = -ENOMEM;
crypt_dec_pending(io);
return;
clone = bio_alloc_bioset(gfp, bio_segments(base_bio), cc->bs);
if (!clone) {
kcryptd_unplug(cc);
return 1;
}

crypt_inc_pending(io);

clone_init(io, clone);
clone->bi_idx = 0;
clone->bi_vcnt = bio_segments(base_bio);
Expand All @@ -816,6 +820,7 @@ static void kcryptd_io_read(struct dm_crypt_io *io)
sizeof(struct bio_vec) * clone->bi_vcnt);

generic_make_request(clone);
return 0;
}

static void kcryptd_io_write(struct dm_crypt_io *io)
Expand All @@ -828,9 +833,12 @@ static void kcryptd_io(struct work_struct *work)
{
struct dm_crypt_io *io = container_of(work, struct dm_crypt_io, work);

if (bio_data_dir(io->base_bio) == READ)
kcryptd_io_read(io);
else
if (bio_data_dir(io->base_bio) == READ) {
crypt_inc_pending(io);
if (kcryptd_io_read(io, GFP_NOIO))
io->error = -ENOMEM;
crypt_dec_pending(io);
} else
kcryptd_io_write(io);
}

Expand Down Expand Up @@ -1424,9 +1432,10 @@ static int crypt_map(struct dm_target *ti, struct bio *bio,

io = crypt_io_alloc(ti, bio, dm_target_offset(ti, bio->bi_sector));

if (bio_data_dir(io->base_bio) == READ)
kcryptd_queue_io(io);
else
if (bio_data_dir(io->base_bio) == READ) {
if (kcryptd_io_read(io, GFP_NOWAIT))
kcryptd_queue_io(io);
} else
kcryptd_queue_crypt(io);

return DM_MAPIO_SUBMITTED;
Expand Down

0 comments on commit 20c8253

Please sign in to comment.