aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2009-04-02 14:55:25 -0400
committerAlasdair G Kergon <agk@redhat.com>2009-04-02 14:55:25 -0400
commitc66213921c816f6b1b16a84911618ba9a363b134 (patch)
tree2b99c1ef34eea840fe3d517d8a20fb59a5a84044 /drivers/md
parent2913808eb56a6445a7b277eb8d17651c8defb035 (diff)
dm snapshot: avoid dropping lock in __find_pending_exception
It is uncommon and bug-prone to drop a lock in a function that is called with the lock held, so this is moved to the caller. Cc: stable@kernel.org Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/dm-snap.c42
1 files changed, 24 insertions, 18 deletions
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 87a2803ba6bd..eb7291a84203 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -992,23 +992,10 @@ __lookup_pending_exception(struct dm_snapshot *s, chunk_t chunk)
992 * this. 992 * this.
993 */ 993 */
994static struct dm_snap_pending_exception * 994static struct dm_snap_pending_exception *
995__find_pending_exception(struct dm_snapshot *s, struct bio *bio) 995__find_pending_exception(struct dm_snapshot *s,
996 struct dm_snap_pending_exception *pe, chunk_t chunk)
996{ 997{
997 struct dm_snap_pending_exception *pe, *pe2; 998 struct dm_snap_pending_exception *pe2;
998 chunk_t chunk = sector_to_chunk(s, bio->bi_sector);
999
1000 /*
1001 * Create a new pending exception, we don't want
1002 * to hold the lock while we do this.
1003 */
1004 up_write(&s->lock);
1005 pe = alloc_pending_exception(s);
1006 down_write(&s->lock);
1007
1008 if (!s->valid) {
1009 free_pending_exception(pe);
1010 return NULL;
1011 }
1012 999
1013 pe2 = __lookup_pending_exception(s, chunk); 1000 pe2 = __lookup_pending_exception(s, chunk);
1014 if (pe2) { 1001 if (pe2) {
@@ -1083,7 +1070,17 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
1083 if (bio_rw(bio) == WRITE) { 1070 if (bio_rw(bio) == WRITE) {
1084 pe = __lookup_pending_exception(s, chunk); 1071 pe = __lookup_pending_exception(s, chunk);
1085 if (!pe) { 1072 if (!pe) {
1086 pe = __find_pending_exception(s, bio); 1073 up_write(&s->lock);
1074 pe = alloc_pending_exception(s);
1075 down_write(&s->lock);
1076
1077 if (!s->valid) {
1078 free_pending_exception(pe);
1079 r = -EIO;
1080 goto out_unlock;
1081 }
1082
1083 pe = __find_pending_exception(s, pe, chunk);
1087 if (!pe) { 1084 if (!pe) {
1088 __invalidate_snapshot(s, -ENOMEM); 1085 __invalidate_snapshot(s, -ENOMEM);
1089 r = -EIO; 1086 r = -EIO;
@@ -1220,7 +1217,16 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio)
1220 1217
1221 pe = __lookup_pending_exception(snap, chunk); 1218 pe = __lookup_pending_exception(snap, chunk);
1222 if (!pe) { 1219 if (!pe) {
1223 pe = __find_pending_exception(snap, bio); 1220 up_write(&snap->lock);
1221 pe = alloc_pending_exception(snap);
1222 down_write(&snap->lock);
1223
1224 if (!snap->valid) {
1225 free_pending_exception(pe);
1226 goto next_snapshot;
1227 }
1228
1229 pe = __find_pending_exception(snap, pe, chunk);
1224 if (!pe) { 1230 if (!pe) {
1225 __invalidate_snapshot(snap, -ENOMEM); 1231 __invalidate_snapshot(snap, -ENOMEM);
1226 goto next_snapshot; 1232 goto next_snapshot;