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