diff options
author | Alasdair G Kergon <agk@redhat.com> | 2006-10-03 04:15:31 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-03 11:04:15 -0400 |
commit | 695368ac3302174531429a90d55c3f7f9b83906e (patch) | |
tree | 515457b78ec2bf95dab7f5b614284ccecda8afbd /drivers/md/dm-snap.c | |
parent | 4b832e8de22726206eb886f6dbff47a0f3fe5168 (diff) |
[PATCH] dm snapshot: fix freeing pending exception
If a snapshot became invalid while there are outstanding pending_exceptions,
when pending_complete() processes each one it forgets to remove the
corresponding exception from its exception table before freeing it.
Fix this by moving the 'out:' label up one statement so that
remove_exception() is always called. Then __invalidate_exception() no longer
needs to call it and its 'pe' argument become superfluous.
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/md/dm-snap.c')
-rw-r--r-- | drivers/md/dm-snap.c | 16 |
1 files changed, 6 insertions, 10 deletions
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 638c8d90da0e..5281e0094072 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c | |||
@@ -631,8 +631,7 @@ static void error_bios(struct bio *bio) | |||
631 | } | 631 | } |
632 | } | 632 | } |
633 | 633 | ||
634 | static void __invalidate_snapshot(struct dm_snapshot *s, | 634 | static void __invalidate_snapshot(struct dm_snapshot *s, int err) |
635 | struct pending_exception *pe, int err) | ||
636 | { | 635 | { |
637 | if (!s->valid) | 636 | if (!s->valid) |
638 | return; | 637 | return; |
@@ -642,9 +641,6 @@ static void __invalidate_snapshot(struct dm_snapshot *s, | |||
642 | else if (err == -ENOMEM) | 641 | else if (err == -ENOMEM) |
643 | DMERR("Invalidating snapshot: Unable to allocate exception."); | 642 | DMERR("Invalidating snapshot: Unable to allocate exception."); |
644 | 643 | ||
645 | if (pe) | ||
646 | remove_exception(&pe->e); | ||
647 | |||
648 | if (s->store.drop_snapshot) | 644 | if (s->store.drop_snapshot) |
649 | s->store.drop_snapshot(&s->store); | 645 | s->store.drop_snapshot(&s->store); |
650 | 646 | ||
@@ -701,7 +697,7 @@ static void pending_complete(struct pending_exception *pe, int success) | |||
701 | if (!success) { | 697 | if (!success) { |
702 | /* Read/write error - snapshot is unusable */ | 698 | /* Read/write error - snapshot is unusable */ |
703 | down_write(&s->lock); | 699 | down_write(&s->lock); |
704 | __invalidate_snapshot(s, pe, -EIO); | 700 | __invalidate_snapshot(s, -EIO); |
705 | error = 1; | 701 | error = 1; |
706 | goto out; | 702 | goto out; |
707 | } | 703 | } |
@@ -709,7 +705,7 @@ static void pending_complete(struct pending_exception *pe, int success) | |||
709 | e = alloc_exception(); | 705 | e = alloc_exception(); |
710 | if (!e) { | 706 | if (!e) { |
711 | down_write(&s->lock); | 707 | down_write(&s->lock); |
712 | __invalidate_snapshot(s, pe, -ENOMEM); | 708 | __invalidate_snapshot(s, -ENOMEM); |
713 | error = 1; | 709 | error = 1; |
714 | goto out; | 710 | goto out; |
715 | } | 711 | } |
@@ -727,9 +723,9 @@ static void pending_complete(struct pending_exception *pe, int success) | |||
727 | * in-flight exception from the list. | 723 | * in-flight exception from the list. |
728 | */ | 724 | */ |
729 | insert_exception(&s->complete, e); | 725 | insert_exception(&s->complete, e); |
730 | remove_exception(&pe->e); | ||
731 | 726 | ||
732 | out: | 727 | out: |
728 | remove_exception(&pe->e); | ||
733 | snapshot_bios = bio_list_get(&pe->snapshot_bios); | 729 | snapshot_bios = bio_list_get(&pe->snapshot_bios); |
734 | origin_bios = put_pending_exception(pe); | 730 | origin_bios = put_pending_exception(pe); |
735 | 731 | ||
@@ -909,7 +905,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio, | |||
909 | if (bio_rw(bio) == WRITE) { | 905 | if (bio_rw(bio) == WRITE) { |
910 | pe = __find_pending_exception(s, bio); | 906 | pe = __find_pending_exception(s, bio); |
911 | if (!pe) { | 907 | if (!pe) { |
912 | __invalidate_snapshot(s, pe, -ENOMEM); | 908 | __invalidate_snapshot(s, -ENOMEM); |
913 | r = -EIO; | 909 | r = -EIO; |
914 | goto out_unlock; | 910 | goto out_unlock; |
915 | } | 911 | } |
@@ -1035,7 +1031,7 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio) | |||
1035 | 1031 | ||
1036 | pe = __find_pending_exception(snap, bio); | 1032 | pe = __find_pending_exception(snap, bio); |
1037 | if (!pe) { | 1033 | if (!pe) { |
1038 | __invalidate_snapshot(snap, pe, -ENOMEM); | 1034 | __invalidate_snapshot(snap, -ENOMEM); |
1039 | goto next_snapshot; | 1035 | goto next_snapshot; |
1040 | } | 1036 | } |
1041 | 1037 | ||