aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/md/dm-snap.c72
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