aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-crypt.c
diff options
context:
space:
mode:
authorMilan Broz <mbroz@redhat.com>2009-03-16 13:44:36 -0400
committerAlasdair G Kergon <agk@redhat.com>2009-03-16 13:44:36 -0400
commitb35f8caa0890169000fec22902290d9a15274cbd (patch)
treea1a8ad3e5ba8b36da631d7125e0deb4ae743955a /drivers/md/dm-crypt.c
parentb2174eebd1fadb76454dad09a1dacbc17081e6b0 (diff)
dm crypt: wait for endio to complete before destruction
The following oops has been reported when dm-crypt runs over a loop device. ... [ 70.381058] Process loop0 (pid: 4268, ti=cf3b2000 task=cf1cc1f0 task.ti=cf3b2000) ... [ 70.381058] Call Trace: [ 70.381058] [<d0d76601>] ? crypt_dec_pending+0x5e/0x62 [dm_crypt] [ 70.381058] [<d0d767b8>] ? crypt_endio+0xa2/0xaa [dm_crypt] [ 70.381058] [<d0d76716>] ? crypt_endio+0x0/0xaa [dm_crypt] [ 70.381058] [<c01a2f24>] ? bio_endio+0x2b/0x2e [ 70.381058] [<d0806530>] ? dec_pending+0x224/0x23b [dm_mod] [ 70.381058] [<d08066e4>] ? clone_endio+0x79/0xa4 [dm_mod] [ 70.381058] [<d080666b>] ? clone_endio+0x0/0xa4 [dm_mod] [ 70.381058] [<c01a2f24>] ? bio_endio+0x2b/0x2e [ 70.381058] [<c02bad86>] ? loop_thread+0x380/0x3b7 [ 70.381058] [<c02ba8a1>] ? do_lo_send_aops+0x0/0x165 [ 70.381058] [<c013754f>] ? autoremove_wake_function+0x0/0x33 [ 70.381058] [<c02baa06>] ? loop_thread+0x0/0x3b7 When a table is being replaced, it waits for I/O to complete before destroying the mempool, but the endio function doesn't call mempool_free() until after completing the bio. Fix it by swapping the order of those two operations. The same problem occurs in dm.c with md referenced after dec_pending. Again, we swap the order. Cc: stable@kernel.org Signed-off-by: Milan Broz <mbroz@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md/dm-crypt.c')
-rw-r--r--drivers/md/dm-crypt.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index ebab49f8cc1d..bfefd079a955 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -568,19 +568,22 @@ static void crypt_inc_pending(struct dm_crypt_io *io)
568static void crypt_dec_pending(struct dm_crypt_io *io) 568static void crypt_dec_pending(struct dm_crypt_io *io)
569{ 569{
570 struct crypt_config *cc = io->target->private; 570 struct crypt_config *cc = io->target->private;
571 struct bio *base_bio = io->base_bio;
572 struct dm_crypt_io *base_io = io->base_io;
573 int error = io->error;
571 574
572 if (!atomic_dec_and_test(&io->pending)) 575 if (!atomic_dec_and_test(&io->pending))
573 return; 576 return;
574 577
575 if (likely(!io->base_io)) 578 mempool_free(io, cc->io_pool);
576 bio_endio(io->base_bio, io->error); 579
580 if (likely(!base_io))
581 bio_endio(base_bio, error);
577 else { 582 else {
578 if (io->error && !io->base_io->error) 583 if (error && !base_io->error)
579 io->base_io->error = io->error; 584 base_io->error = error;
580 crypt_dec_pending(io->base_io); 585 crypt_dec_pending(base_io);
581 } 586 }
582
583 mempool_free(io, cc->io_pool);
584} 587}
585 588
586/* 589/*