diff options
Diffstat (limited to 'drivers/md/dm-snap.c')
-rw-r--r-- | drivers/md/dm-snap.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index de302702ab3e..f4fd0cee9c3d 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c | |||
@@ -134,6 +134,27 @@ static void stop_tracking_chunk(struct dm_snapshot *s, | |||
134 | mempool_free(c, s->tracked_chunk_pool); | 134 | mempool_free(c, s->tracked_chunk_pool); |
135 | } | 135 | } |
136 | 136 | ||
137 | static int __chunk_is_tracked(struct dm_snapshot *s, chunk_t chunk) | ||
138 | { | ||
139 | struct dm_snap_tracked_chunk *c; | ||
140 | struct hlist_node *hn; | ||
141 | int found = 0; | ||
142 | |||
143 | spin_lock_irq(&s->tracked_chunk_lock); | ||
144 | |||
145 | hlist_for_each_entry(c, hn, | ||
146 | &s->tracked_chunk_hash[DM_TRACKED_CHUNK_HASH(chunk)], node) { | ||
147 | if (c->chunk == chunk) { | ||
148 | found = 1; | ||
149 | break; | ||
150 | } | ||
151 | } | ||
152 | |||
153 | spin_unlock_irq(&s->tracked_chunk_lock); | ||
154 | |||
155 | return found; | ||
156 | } | ||
157 | |||
137 | /* | 158 | /* |
138 | * One of these per registered origin, held in the snapshot_origins hash | 159 | * One of these per registered origin, held in the snapshot_origins hash |
139 | */ | 160 | */ |
@@ -840,6 +861,13 @@ static void pending_complete(struct dm_snap_pending_exception *pe, int success) | |||
840 | } | 861 | } |
841 | 862 | ||
842 | /* | 863 | /* |
864 | * Check for conflicting reads. This is extremely improbable, | ||
865 | * so yield() is sufficient and there is no need for a wait queue. | ||
866 | */ | ||
867 | while (__chunk_is_tracked(s, pe->e.old_chunk)) | ||
868 | yield(); | ||
869 | |||
870 | /* | ||
843 | * Add a proper exception, and remove the | 871 | * Add a proper exception, and remove the |
844 | * in-flight exception from the list. | 872 | * in-flight exception from the list. |
845 | */ | 873 | */ |