diff options
author | Alasdair G Kergon <agk@redhat.com> | 2006-10-03 04:15:30 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-03 11:04:14 -0400 |
commit | 4b832e8de22726206eb886f6dbff47a0f3fe5168 (patch) | |
tree | 279cf60137cc08f4f4ae17f04940d69d68262b10 | |
parent | ca3a931fd33b841cbcc5932f8eac7c43e0909242 (diff) |
[PATCH] dm snapshot: tidy pe ref counting
Rename sibling_count to ref_count and introduce get and put functions.
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>
-rw-r--r-- | drivers/md/dm-snap.c | 83 |
1 files changed, 48 insertions, 35 deletions
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 1c6485404db4..638c8d90da0e 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c | |||
@@ -59,7 +59,7 @@ struct pending_exception { | |||
59 | 59 | ||
60 | /* | 60 | /* |
61 | * The primary pending_exception is the one that holds | 61 | * The primary pending_exception is the one that holds |
62 | * the sibling_count and the list of origin_bios for a | 62 | * the ref_count and the list of origin_bios for a |
63 | * group of pending_exceptions. It is always last to get freed. | 63 | * group of pending_exceptions. It is always last to get freed. |
64 | * These fields get set up when writing to the origin. | 64 | * These fields get set up when writing to the origin. |
65 | */ | 65 | */ |
@@ -72,7 +72,7 @@ struct pending_exception { | |||
72 | * the sibling concerned and not pe->primary_pe->snap->lock unless | 72 | * the sibling concerned and not pe->primary_pe->snap->lock unless |
73 | * they are the same. | 73 | * they are the same. |
74 | */ | 74 | */ |
75 | atomic_t sibling_count; | 75 | atomic_t ref_count; |
76 | 76 | ||
77 | /* Pointer back to snapshot context */ | 77 | /* Pointer back to snapshot context */ |
78 | struct dm_snapshot *snap; | 78 | struct dm_snapshot *snap; |
@@ -653,10 +653,46 @@ static void __invalidate_snapshot(struct dm_snapshot *s, | |||
653 | dm_table_event(s->table); | 653 | dm_table_event(s->table); |
654 | } | 654 | } |
655 | 655 | ||
656 | static void get_pending_exception(struct pending_exception *pe) | ||
657 | { | ||
658 | atomic_inc(&pe->ref_count); | ||
659 | } | ||
660 | |||
661 | static struct bio *put_pending_exception(struct pending_exception *pe) | ||
662 | { | ||
663 | struct pending_exception *primary_pe; | ||
664 | struct bio *origin_bios = NULL; | ||
665 | |||
666 | primary_pe = pe->primary_pe; | ||
667 | |||
668 | /* | ||
669 | * If this pe is involved in a write to the origin and | ||
670 | * it is the last sibling to complete then release | ||
671 | * the bios for the original write to the origin. | ||
672 | */ | ||
673 | if (primary_pe && | ||
674 | atomic_dec_and_test(&primary_pe->ref_count)) | ||
675 | origin_bios = bio_list_get(&primary_pe->origin_bios); | ||
676 | |||
677 | /* | ||
678 | * Free the pe if it's not linked to an origin write or if | ||
679 | * it's not itself a primary pe. | ||
680 | */ | ||
681 | if (!primary_pe || primary_pe != pe) | ||
682 | free_pending_exception(pe); | ||
683 | |||
684 | /* | ||
685 | * Free the primary pe if nothing references it. | ||
686 | */ | ||
687 | if (primary_pe && !atomic_read(&primary_pe->ref_count)) | ||
688 | free_pending_exception(primary_pe); | ||
689 | |||
690 | return origin_bios; | ||
691 | } | ||
692 | |||
656 | static void pending_complete(struct pending_exception *pe, int success) | 693 | static void pending_complete(struct pending_exception *pe, int success) |
657 | { | 694 | { |
658 | struct exception *e; | 695 | struct exception *e; |
659 | struct pending_exception *primary_pe; | ||
660 | struct dm_snapshot *s = pe->snap; | 696 | struct dm_snapshot *s = pe->snap; |
661 | struct bio *origin_bios = NULL; | 697 | struct bio *origin_bios = NULL; |
662 | struct bio *snapshot_bios = NULL; | 698 | struct bio *snapshot_bios = NULL; |
@@ -695,30 +731,7 @@ static void pending_complete(struct pending_exception *pe, int success) | |||
695 | 731 | ||
696 | out: | 732 | out: |
697 | snapshot_bios = bio_list_get(&pe->snapshot_bios); | 733 | snapshot_bios = bio_list_get(&pe->snapshot_bios); |
698 | 734 | origin_bios = put_pending_exception(pe); | |
699 | primary_pe = pe->primary_pe; | ||
700 | |||
701 | /* | ||
702 | * If this pe is involved in a write to the origin and | ||
703 | * it is the last sibling to complete then release | ||
704 | * the bios for the original write to the origin. | ||
705 | */ | ||
706 | if (primary_pe && | ||
707 | atomic_dec_and_test(&primary_pe->sibling_count)) | ||
708 | origin_bios = bio_list_get(&primary_pe->origin_bios); | ||
709 | |||
710 | /* | ||
711 | * Free the pe if it's not linked to an origin write or if | ||
712 | * it's not itself a primary pe. | ||
713 | */ | ||
714 | if (!primary_pe || primary_pe != pe) | ||
715 | free_pending_exception(pe); | ||
716 | |||
717 | /* | ||
718 | * Free the primary pe if nothing references it. | ||
719 | */ | ||
720 | if (primary_pe && !atomic_read(&primary_pe->sibling_count)) | ||
721 | free_pending_exception(primary_pe); | ||
722 | 735 | ||
723 | up_write(&s->lock); | 736 | up_write(&s->lock); |
724 | 737 | ||
@@ -829,7 +842,7 @@ __find_pending_exception(struct dm_snapshot *s, struct bio *bio) | |||
829 | bio_list_init(&pe->origin_bios); | 842 | bio_list_init(&pe->origin_bios); |
830 | bio_list_init(&pe->snapshot_bios); | 843 | bio_list_init(&pe->snapshot_bios); |
831 | pe->primary_pe = NULL; | 844 | pe->primary_pe = NULL; |
832 | atomic_set(&pe->sibling_count, 1); | 845 | atomic_set(&pe->ref_count, 0); |
833 | pe->snap = s; | 846 | pe->snap = s; |
834 | pe->started = 0; | 847 | pe->started = 0; |
835 | 848 | ||
@@ -838,6 +851,7 @@ __find_pending_exception(struct dm_snapshot *s, struct bio *bio) | |||
838 | return NULL; | 851 | return NULL; |
839 | } | 852 | } |
840 | 853 | ||
854 | get_pending_exception(pe); | ||
841 | insert_exception(&s->pending, &pe->e); | 855 | insert_exception(&s->pending, &pe->e); |
842 | 856 | ||
843 | out: | 857 | out: |
@@ -1012,7 +1026,7 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio) | |||
1012 | * is already remapped in this snapshot | 1026 | * is already remapped in this snapshot |
1013 | * and trigger an exception if not. | 1027 | * and trigger an exception if not. |
1014 | * | 1028 | * |
1015 | * sibling_count is initialised to 1 so pending_complete() | 1029 | * ref_count is initialised to 1 so pending_complete() |
1016 | * won't destroy the primary_pe while we're inside this loop. | 1030 | * won't destroy the primary_pe while we're inside this loop. |
1017 | */ | 1031 | */ |
1018 | e = lookup_exception(&snap->complete, chunk); | 1032 | e = lookup_exception(&snap->complete, chunk); |
@@ -1043,8 +1057,8 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio) | |||
1043 | } | 1057 | } |
1044 | 1058 | ||
1045 | if (!pe->primary_pe) { | 1059 | if (!pe->primary_pe) { |
1046 | atomic_inc(&primary_pe->sibling_count); | ||
1047 | pe->primary_pe = primary_pe; | 1060 | pe->primary_pe = primary_pe; |
1061 | get_pending_exception(primary_pe); | ||
1048 | } | 1062 | } |
1049 | 1063 | ||
1050 | if (!pe->started) { | 1064 | if (!pe->started) { |
@@ -1057,20 +1071,20 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio) | |||
1057 | } | 1071 | } |
1058 | 1072 | ||
1059 | if (!primary_pe) | 1073 | if (!primary_pe) |
1060 | goto out; | 1074 | return r; |
1061 | 1075 | ||
1062 | /* | 1076 | /* |
1063 | * If this is the first time we're processing this chunk and | 1077 | * If this is the first time we're processing this chunk and |
1064 | * sibling_count is now 1 it means all the pending exceptions | 1078 | * ref_count is now 1 it means all the pending exceptions |
1065 | * got completed while we were in the loop above, so it falls to | 1079 | * got completed while we were in the loop above, so it falls to |
1066 | * us here to remove the primary_pe and submit any origin_bios. | 1080 | * us here to remove the primary_pe and submit any origin_bios. |
1067 | */ | 1081 | */ |
1068 | 1082 | ||
1069 | if (first && atomic_dec_and_test(&primary_pe->sibling_count)) { | 1083 | if (first && atomic_dec_and_test(&primary_pe->ref_count)) { |
1070 | flush_bios(bio_list_get(&primary_pe->origin_bios)); | 1084 | flush_bios(bio_list_get(&primary_pe->origin_bios)); |
1071 | free_pending_exception(primary_pe); | 1085 | free_pending_exception(primary_pe); |
1072 | /* If we got here, pe_queue is necessarily empty. */ | 1086 | /* If we got here, pe_queue is necessarily empty. */ |
1073 | goto out; | 1087 | return r; |
1074 | } | 1088 | } |
1075 | 1089 | ||
1076 | /* | 1090 | /* |
@@ -1079,7 +1093,6 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio) | |||
1079 | list_for_each_entry_safe(pe, next_pe, &pe_queue, list) | 1093 | list_for_each_entry_safe(pe, next_pe, &pe_queue, list) |
1080 | start_copy(pe); | 1094 | start_copy(pe); |
1081 | 1095 | ||
1082 | out: | ||
1083 | return r; | 1096 | return r; |
1084 | } | 1097 | } |
1085 | 1098 | ||