diff options
Diffstat (limited to 'drivers/md/dm-snap.c')
-rw-r--r-- | drivers/md/dm-snap.c | 72 |
1 files changed, 26 insertions, 46 deletions
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 58c444fb189c..c5449f2504b6 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c | |||
@@ -851,7 +851,6 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio, | |||
851 | { | 851 | { |
852 | struct exception *e; | 852 | struct exception *e; |
853 | struct dm_snapshot *s = (struct dm_snapshot *) ti->private; | 853 | struct dm_snapshot *s = (struct dm_snapshot *) ti->private; |
854 | int copy_needed = 0; | ||
855 | int r = 1; | 854 | int r = 1; |
856 | chunk_t chunk; | 855 | chunk_t chunk; |
857 | struct pending_exception *pe = NULL; | 856 | struct pending_exception *pe = NULL; |
@@ -866,29 +865,28 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio, | |||
866 | if (unlikely(bio_barrier(bio))) | 865 | if (unlikely(bio_barrier(bio))) |
867 | return -EOPNOTSUPP; | 866 | return -EOPNOTSUPP; |
868 | 867 | ||
868 | /* FIXME: should only take write lock if we need | ||
869 | * to copy an exception */ | ||
870 | down_write(&s->lock); | ||
871 | |||
872 | if (!s->valid) { | ||
873 | r = -EIO; | ||
874 | goto out_unlock; | ||
875 | } | ||
876 | |||
877 | /* If the block is already remapped - use that, else remap it */ | ||
878 | e = lookup_exception(&s->complete, chunk); | ||
879 | if (e) { | ||
880 | remap_exception(s, e, bio); | ||
881 | goto out_unlock; | ||
882 | } | ||
883 | |||
869 | /* | 884 | /* |
870 | * Write to snapshot - higher level takes care of RW/RO | 885 | * Write to snapshot - higher level takes care of RW/RO |
871 | * flags so we should only get this if we are | 886 | * flags so we should only get this if we are |
872 | * writeable. | 887 | * writeable. |
873 | */ | 888 | */ |
874 | if (bio_rw(bio) == WRITE) { | 889 | if (bio_rw(bio) == WRITE) { |
875 | |||
876 | /* FIXME: should only take write lock if we need | ||
877 | * to copy an exception */ | ||
878 | down_write(&s->lock); | ||
879 | |||
880 | if (!s->valid) { | ||
881 | r = -EIO; | ||
882 | goto out_unlock; | ||
883 | } | ||
884 | |||
885 | /* If the block is already remapped - use that, else remap it */ | ||
886 | e = lookup_exception(&s->complete, chunk); | ||
887 | if (e) { | ||
888 | remap_exception(s, e, bio); | ||
889 | goto out_unlock; | ||
890 | } | ||
891 | |||
892 | pe = __find_pending_exception(s, bio); | 890 | pe = __find_pending_exception(s, bio); |
893 | if (!pe) { | 891 | if (!pe) { |
894 | __invalidate_snapshot(s, pe, -ENOMEM); | 892 | __invalidate_snapshot(s, pe, -ENOMEM); |
@@ -899,45 +897,27 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio, | |||
899 | remap_exception(s, &pe->e, bio); | 897 | remap_exception(s, &pe->e, bio); |
900 | bio_list_add(&pe->snapshot_bios, bio); | 898 | bio_list_add(&pe->snapshot_bios, bio); |
901 | 899 | ||
900 | r = 0; | ||
901 | |||
902 | if (!pe->started) { | 902 | if (!pe->started) { |
903 | /* this is protected by snap->lock */ | 903 | /* this is protected by snap->lock */ |
904 | pe->started = 1; | 904 | pe->started = 1; |
905 | copy_needed = 1; | 905 | up_write(&s->lock); |
906 | } | ||
907 | |||
908 | r = 0; | ||
909 | |||
910 | out_unlock: | ||
911 | up_write(&s->lock); | ||
912 | |||
913 | if (copy_needed) | ||
914 | start_copy(pe); | 906 | start_copy(pe); |
915 | } else { | 907 | goto out; |
908 | } | ||
909 | } else | ||
916 | /* | 910 | /* |
917 | * FIXME: this read path scares me because we | 911 | * FIXME: this read path scares me because we |
918 | * always use the origin when we have a pending | 912 | * always use the origin when we have a pending |
919 | * exception. However I can't think of a | 913 | * exception. However I can't think of a |
920 | * situation where this is wrong - ejt. | 914 | * situation where this is wrong - ejt. |
921 | */ | 915 | */ |
916 | bio->bi_bdev = s->origin->bdev; | ||
922 | 917 | ||
923 | /* Do reads */ | 918 | out_unlock: |
924 | down_read(&s->lock); | 919 | up_write(&s->lock); |
925 | 920 | out: | |
926 | if (!s->valid) { | ||
927 | up_read(&s->lock); | ||
928 | return -EIO; | ||
929 | } | ||
930 | |||
931 | /* See if it it has been remapped */ | ||
932 | e = lookup_exception(&s->complete, chunk); | ||
933 | if (e) | ||
934 | remap_exception(s, e, bio); | ||
935 | else | ||
936 | bio->bi_bdev = s->origin->bdev; | ||
937 | |||
938 | up_read(&s->lock); | ||
939 | } | ||
940 | |||
941 | return r; | 921 | return r; |
942 | } | 922 | } |
943 | 923 | ||