diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/md/dm-crypt.c | 17 | ||||
| -rw-r--r-- | drivers/md/dm.c | 32 |
2 files changed, 29 insertions, 20 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) | |||
| 568 | static void crypt_dec_pending(struct dm_crypt_io *io) | 568 | static 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 | /* |
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 51ba1db4b3e7..8d40f27cce89 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
| @@ -525,9 +525,12 @@ static int __noflush_suspending(struct mapped_device *md) | |||
| 525 | static void dec_pending(struct dm_io *io, int error) | 525 | static void dec_pending(struct dm_io *io, int error) |
| 526 | { | 526 | { |
| 527 | unsigned long flags; | 527 | unsigned long flags; |
| 528 | int io_error; | ||
| 529 | struct bio *bio; | ||
| 530 | struct mapped_device *md = io->md; | ||
| 528 | 531 | ||
| 529 | /* Push-back supersedes any I/O errors */ | 532 | /* Push-back supersedes any I/O errors */ |
| 530 | if (error && !(io->error > 0 && __noflush_suspending(io->md))) | 533 | if (error && !(io->error > 0 && __noflush_suspending(md))) |
| 531 | io->error = error; | 534 | io->error = error; |
| 532 | 535 | ||
| 533 | if (atomic_dec_and_test(&io->io_count)) { | 536 | if (atomic_dec_and_test(&io->io_count)) { |
| @@ -537,24 +540,27 @@ static void dec_pending(struct dm_io *io, int error) | |||
| 537 | * This must be handled before the sleeper on | 540 | * This must be handled before the sleeper on |
| 538 | * suspend queue merges the pushback list. | 541 | * suspend queue merges the pushback list. |
| 539 | */ | 542 | */ |
| 540 | spin_lock_irqsave(&io->md->pushback_lock, flags); | 543 | spin_lock_irqsave(&md->pushback_lock, flags); |
| 541 | if (__noflush_suspending(io->md)) | 544 | if (__noflush_suspending(md)) |
| 542 | bio_list_add(&io->md->pushback, io->bio); | 545 | bio_list_add(&md->pushback, io->bio); |
| 543 | else | 546 | else |
| 544 | /* noflush suspend was interrupted. */ | 547 | /* noflush suspend was interrupted. */ |
| 545 | io->error = -EIO; | 548 | io->error = -EIO; |
| 546 | spin_unlock_irqrestore(&io->md->pushback_lock, flags); | 549 | spin_unlock_irqrestore(&md->pushback_lock, flags); |
| 547 | } | 550 | } |
| 548 | 551 | ||
| 549 | end_io_acct(io); | 552 | end_io_acct(io); |
| 550 | 553 | ||
| 551 | if (io->error != DM_ENDIO_REQUEUE) { | 554 | io_error = io->error; |
| 552 | trace_block_bio_complete(io->md->queue, io->bio); | 555 | bio = io->bio; |
| 553 | 556 | ||
| 554 | bio_endio(io->bio, io->error); | 557 | free_io(md, io); |
| 555 | } | 558 | |
| 559 | if (io_error != DM_ENDIO_REQUEUE) { | ||
| 560 | trace_block_bio_complete(md->queue, bio); | ||
| 556 | 561 | ||
| 557 | free_io(io->md, io); | 562 | bio_endio(bio, io_error); |
| 563 | } | ||
| 558 | } | 564 | } |
| 559 | } | 565 | } |
| 560 | 566 | ||
| @@ -562,6 +568,7 @@ static void clone_endio(struct bio *bio, int error) | |||
| 562 | { | 568 | { |
| 563 | int r = 0; | 569 | int r = 0; |
| 564 | struct dm_target_io *tio = bio->bi_private; | 570 | struct dm_target_io *tio = bio->bi_private; |
| 571 | struct dm_io *io = tio->io; | ||
| 565 | struct mapped_device *md = tio->io->md; | 572 | struct mapped_device *md = tio->io->md; |
| 566 | dm_endio_fn endio = tio->ti->type->end_io; | 573 | dm_endio_fn endio = tio->ti->type->end_io; |
| 567 | 574 | ||
| @@ -585,15 +592,14 @@ static void clone_endio(struct bio *bio, int error) | |||
| 585 | } | 592 | } |
| 586 | } | 593 | } |
| 587 | 594 | ||
| 588 | dec_pending(tio->io, error); | ||
| 589 | |||
| 590 | /* | 595 | /* |
| 591 | * Store md for cleanup instead of tio which is about to get freed. | 596 | * Store md for cleanup instead of tio which is about to get freed. |
| 592 | */ | 597 | */ |
| 593 | bio->bi_private = md->bs; | 598 | bio->bi_private = md->bs; |
| 594 | 599 | ||
| 595 | bio_put(bio); | ||
| 596 | free_tio(md, tio); | 600 | free_tio(md, tio); |
| 601 | bio_put(bio); | ||
| 602 | dec_pending(io, error); | ||
| 597 | } | 603 | } |
| 598 | 604 | ||
| 599 | static sector_t max_io_len(struct mapped_device *md, | 605 | static sector_t max_io_len(struct mapped_device *md, |
