Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dm snapshot: fix race during exception creation

Fix a race condition that returns incorrect data when a write causes an
exception to be allocated whilst a read is still in flight.

The race condition happens as follows:
* A read to non-reallocated sector in the snapshot is submitted so that the
read is routed to the original device.
* A write to the original device is submitted. The write causes an exception
that reallocates the block. The write proceeds.
* The original read is dequeued and reads the wrong data.

This race can be triggered with CFQ scheduler and one thread writing and
multiple threads reading simultaneously.

(This patch relies upon the earlier dm-kcopyd-per-device.patch to avoid a
deadlock.)

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>

authored by

Mikulas Patocka and committed by
Alasdair G Kergon
a8d41b59 cd45daff

+28
+28
drivers/md/dm-snap.c
··· 134 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 159 * One of these per registered origin, held in the snapshot_origins hash 139 160 */ ··· 859 838 error = 1; 860 839 goto out; 861 840 } 841 + 842 + /* 843 + * Check for conflicting reads. This is extremely improbable, 844 + * so yield() is sufficient and there is no need for a wait queue. 845 + */ 846 + while (__chunk_is_tracked(s, pe->e.old_chunk)) 847 + yield(); 862 848 863 849 /* 864 850 * Add a proper exception, and remove the