aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-snap.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/dm-snap.c')
-rw-r--r--drivers/md/dm-snap.c76
1 files changed, 30 insertions, 46 deletions
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index c5449f2504b6..d92980177b5c 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -609,26 +609,6 @@ static void error_bios(struct bio *bio)
609 } 609 }
610} 610}
611 611
612static inline void error_snapshot_bios(struct pending_exception *pe)
613{
614 error_bios(bio_list_get(&pe->snapshot_bios));
615}
616
617static struct bio *__flush_bios(struct pending_exception *pe)
618{
619 /*
620 * If this pe is involved in a write to the origin and
621 * it is the last sibling to complete then release
622 * the bios for the original write to the origin.
623 */
624
625 if (pe->primary_pe &&
626 atomic_dec_and_test(&pe->primary_pe->sibling_count))
627 return bio_list_get(&pe->primary_pe->origin_bios);
628
629 return NULL;
630}
631
632static void __invalidate_snapshot(struct dm_snapshot *s, 612static void __invalidate_snapshot(struct dm_snapshot *s,
633 struct pending_exception *pe, int err) 613 struct pending_exception *pe, int err)
634{ 614{
@@ -656,16 +636,15 @@ static void pending_complete(struct pending_exception *pe, int success)
656 struct exception *e; 636 struct exception *e;
657 struct pending_exception *primary_pe; 637 struct pending_exception *primary_pe;
658 struct dm_snapshot *s = pe->snap; 638 struct dm_snapshot *s = pe->snap;
659 struct bio *flush = NULL; 639 struct bio *origin_bios = NULL;
640 struct bio *snapshot_bios = NULL;
641 int error = 0;
660 642
661 if (!success) { 643 if (!success) {
662 /* Read/write error - snapshot is unusable */ 644 /* Read/write error - snapshot is unusable */
663 down_write(&s->lock); 645 down_write(&s->lock);
664 __invalidate_snapshot(s, pe, -EIO); 646 __invalidate_snapshot(s, pe, -EIO);
665 flush = __flush_bios(pe); 647 error = 1;
666 up_write(&s->lock);
667
668 error_snapshot_bios(pe);
669 goto out; 648 goto out;
670 } 649 }
671 650
@@ -673,42 +652,40 @@ static void pending_complete(struct pending_exception *pe, int success)
673 if (!e) { 652 if (!e) {
674 down_write(&s->lock); 653 down_write(&s->lock);
675 __invalidate_snapshot(s, pe, -ENOMEM); 654 __invalidate_snapshot(s, pe, -ENOMEM);
676 flush = __flush_bios(pe); 655 error = 1;
677 up_write(&s->lock);
678
679 error_snapshot_bios(pe);
680 goto out; 656 goto out;
681 } 657 }
682 *e = pe->e; 658 *e = pe->e;
683 659
684 /*
685 * Add a proper exception, and remove the
686 * in-flight exception from the list.
687 */
688 down_write(&s->lock); 660 down_write(&s->lock);
689 if (!s->valid) { 661 if (!s->valid) {
690 flush = __flush_bios(pe);
691 up_write(&s->lock);
692
693 free_exception(e); 662 free_exception(e);
694 663 error = 1;
695 error_snapshot_bios(pe);
696 goto out; 664 goto out;
697 } 665 }
698 666
667 /*
668 * Add a proper exception, and remove the
669 * in-flight exception from the list.
670 */
699 insert_exception(&s->complete, e); 671 insert_exception(&s->complete, e);
700 remove_exception(&pe->e); 672 remove_exception(&pe->e);
701 flush = __flush_bios(pe);
702
703 up_write(&s->lock);
704
705 /* Submit any pending write bios */
706 flush_bios(bio_list_get(&pe->snapshot_bios));
707 673
708 out: 674 out:
675 snapshot_bios = bio_list_get(&pe->snapshot_bios);
676
709 primary_pe = pe->primary_pe; 677 primary_pe = pe->primary_pe;
710 678
711 /* 679 /*
680 * If this pe is involved in a write to the origin and
681 * it is the last sibling to complete then release
682 * the bios for the original write to the origin.
683 */
684 if (primary_pe &&
685 atomic_dec_and_test(&primary_pe->sibling_count))
686 origin_bios = bio_list_get(&primary_pe->origin_bios);
687
688 /*
712 * Free the pe if it's not linked to an origin write or if 689 * Free the pe if it's not linked to an origin write or if
713 * it's not itself a primary pe. 690 * it's not itself a primary pe.
714 */ 691 */
@@ -721,8 +698,15 @@ static void pending_complete(struct pending_exception *pe, int success)
721 if (primary_pe && !atomic_read(&primary_pe->sibling_count)) 698 if (primary_pe && !atomic_read(&primary_pe->sibling_count))
722 free_pending_exception(primary_pe); 699 free_pending_exception(primary_pe);
723 700
724 if (flush) 701 up_write(&s->lock);
725 flush_bios(flush); 702
703 /* Submit any pending write bios */
704 if (error)
705 error_bios(snapshot_bios);
706 else
707 flush_bios(snapshot_bios);
708
709 flush_bios(origin_bios);
726} 710}
727 711
728static void commit_callback(void *context, int success) 712static void commit_callback(void *context, int success)