diff options
author | Olaf Kirch <olaf.kirch@oracle.com> | 2007-05-09 13:32:52 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-09 23:30:46 +0400 |
commit | 027581f3515b5ec2218847dab578afa439a9d6b9 (patch) | |
tree | a15a2e0f3711c42a70170b9d4232b61d694899ca /drivers/md | |
parent | 9c89f8be1a7d14aad9d2c3f7d90d7d88f82c61e2 (diff) | |
download | linux-027581f3515b5ec2218847dab578afa439a9d6b9.tar.xz |
dm crypt: fix call to clone_init
Call clone_init early
We need to call clone_init as early as possible - at least before call
bio_put(clone) in any error path. Otherwise, the destructor will try to
dereference bi_private, which may still be NULL.
Signed-off-by: Olaf Kirch <olaf.kirch@oracle.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/dm-crypt.c | 12 |
1 files changed, 7 insertions, 5 deletions
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 8527827b24f1..db439363f97d 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -107,6 +107,8 @@ struct crypt_config { static struct kmem_cache *_crypt_io_pool; +static void clone_init(struct crypt_io *, struct bio *); + /* * Different IV generation algorithms: * @@ -379,9 +381,10 @@ static int crypt_convert(struct crypt_config *cc, * May return a smaller bio when running out of pages */ static struct bio * -crypt_alloc_buffer(struct crypt_config *cc, unsigned int size, +crypt_alloc_buffer(struct crypt_io *io, unsigned int size, struct bio *base_bio, unsigned int *bio_vec_idx) { + struct crypt_config *cc = io->target->private; struct bio *clone; unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; gfp_t gfp_mask = GFP_NOIO | __GFP_HIGHMEM; @@ -396,7 +399,7 @@ crypt_alloc_buffer(struct crypt_config *cc, unsigned int size, if (!clone) return NULL; - clone->bi_destructor = dm_crypt_bio_destructor; + clone_init(io, clone); /* if the last bio was not complete, continue where that one ended */ clone->bi_idx = *bio_vec_idx; @@ -562,6 +565,7 @@ static void clone_init(struct crypt_io *io, struct bio *clone) clone->bi_end_io = crypt_endio; clone->bi_bdev = cc->dev->bdev; clone->bi_rw = io->base_bio->bi_rw; + clone->bi_destructor = dm_crypt_bio_destructor; } static void process_read(struct crypt_io *io) @@ -585,7 +589,6 @@ static void process_read(struct crypt_io *io) } clone_init(io, clone); - clone->bi_destructor = dm_crypt_bio_destructor; clone->bi_idx = 0; clone->bi_vcnt = bio_segments(base_bio); clone->bi_size = base_bio->bi_size; @@ -615,7 +618,7 @@ static void process_write(struct crypt_io *io) * so repeat the whole process until all the data can be handled. */ while (remaining) { - clone = crypt_alloc_buffer(cc, base_bio->bi_size, + clone = crypt_alloc_buffer(io, base_bio->bi_size, io->first_clone, &bvec_idx); if (unlikely(!clone)) { dec_pending(io, -ENOMEM); @@ -631,7 +634,6 @@ static void process_write(struct crypt_io *io) return; } - clone_init(io, clone); clone->bi_sector = cc->start + sector; if (!io->first_clone) { |