diff options
author | Mikulas Patocka <mpatocka@redhat.com> | 2009-04-02 14:55:25 -0400 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2009-04-02 14:55:25 -0400 |
commit | c66213921c816f6b1b16a84911618ba9a363b134 (patch) | |
tree | 2b99c1ef34eea840fe3d517d8a20fb59a5a84044 /drivers/md | |
parent | 2913808eb56a6445a7b277eb8d17651c8defb035 (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.c | 42 |
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 | */ |
994 | static struct dm_snap_pending_exception * | 994 | static 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; |