Move snapshot locking to a separate function. Signed-off-by: Mikulas Patocka --- drivers/md/dm-snap.c | 82 +++++++++++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 35 deletions(-) Index: linux-2.6.31-fast-new-2/drivers/md/dm-snap.c =================================================================== --- linux-2.6.31-fast-new-2.orig/drivers/md/dm-snap.c 2009-10-16 21:52:05.000000000 +0200 +++ linux-2.6.31-fast-new-2/drivers/md/dm-snap.c 2009-10-16 21:52:43.000000000 +0200 @@ -323,6 +323,18 @@ static void __insert_origin(struct origi list_add_tail(&o->hash_list, sl); } +#define LOCK_DEPTH 0xff + +static void lock_snapshot(struct dm_snapshot *s, int flags) +{ + down_write_nested(&s->lock, flags & LOCK_DEPTH); +} + +static void unlock_snapshot(struct dm_snapshot *s, int flags) +{ + up_write(&s->lock); +} + static struct dm_snapshot *__find_merging_snapshot(struct block_device *origin) { struct origin *o; @@ -744,10 +756,10 @@ test_again: goto test_again; } - down_write(&s->lock); + lock_snapshot(s, 0); s->merge_write_interlock = old_chunk; s->merge_write_interlock_n = linear_chunks; - up_write(&s->lock); + unlock_snapshot(s, 0); /* Wait until writes to all 'linear_chunks' drain */ for (i = 0; i < linear_chunks; i++) { @@ -769,7 +781,7 @@ static inline void release_write_interlo s->merge_write_interlock = 0; s->merge_write_interlock_n = 0; b = bio_list_get(&s->merge_write_list); - up_write(&s->lock); + unlock_snapshot(s, 0); if (!err) flush_bios(b); else @@ -796,7 +808,7 @@ static void merge_callback(int read_err, goto shut; } - down_write(&s->lock); + lock_snapshot(s, 0); /* * Must process chunks (and associated exceptions) in reverse * so that dm_consecutive_chunk_count_dec() accounting works @@ -808,7 +820,7 @@ static void merge_callback(int read_err, DMERR("exception for block %llu is on " "disk but not in memory", (unsigned long long)old_chunk); - up_write(&s->lock); + unlock_snapshot(s, 0); goto shut; } if (dm_consecutive_chunk_count(e)) { @@ -818,7 +830,7 @@ static void merge_callback(int read_err, } else if (old_chunk != e->old_chunk + dm_consecutive_chunk_count(e)) { DMERR("merge from the middle of a chunk range"); - up_write(&s->lock); + unlock_snapshot(s, 0); goto shut; } dm_consecutive_chunk_count_dec(e); @@ -833,7 +845,7 @@ static void merge_callback(int read_err, return; shut: - down_write(&s->lock); + lock_snapshot(s, 0); release_write_interlock(s, 1); s->merge_running = 0; } @@ -1105,14 +1117,14 @@ static void snapshot_dtr(struct dm_targe struct dm_snapshot *s = ti->private; /* This snapshot may need to handover its exception store */ - down_write(&s->lock); + lock_snapshot(s, 0); if (s->handover_snap) { struct dm_snapshot *new_snap = s->handover_snap; - down_write_nested(&new_snap->lock, SINGLE_DEPTH_NESTING); + lock_snapshot(new_snap, 1); handover_exceptions(s, new_snap); - up_write(&new_snap->lock); + unlock_snapshot(new_snap, 1); } - up_write(&s->lock); + unlock_snapshot(s, 0); if (is_merge(ti)) stop_merge(s); @@ -1243,7 +1255,7 @@ static void pending_complete(struct dm_s if (!success) { /* Read/write error - snapshot is unusable */ - down_write(&s->lock); + lock_snapshot(s, 0); __invalidate_snapshot(s, -EIO); error = 1; goto out; @@ -1251,14 +1263,14 @@ static void pending_complete(struct dm_s e = alloc_completed_exception(); if (!e) { - down_write(&s->lock); + lock_snapshot(s, 0); __invalidate_snapshot(s, -ENOMEM); error = 1; goto out; } *e = pe->e; - down_write(&s->lock); + lock_snapshot(s, 0); if (!s->valid) { free_completed_exception(e); error = 1; @@ -1286,7 +1298,7 @@ static void pending_complete(struct dm_s wake_up_all(&_pending_exception_done); - up_write(&s->lock); + unlock_snapshot(s, 0); /* Submit any pending write bios */ if (error) @@ -1427,7 +1439,7 @@ static int snapshot_map(struct dm_target /* FIXME: should only take write lock if we need * to copy an exception */ - down_write(&s->lock); + lock_snapshot(s, 0); if (!s->valid) { r = -EIO; @@ -1449,9 +1461,9 @@ static int snapshot_map(struct dm_target if (bio_rw(bio) == WRITE) { pe = __lookup_pending_exception(s, chunk); if (!pe) { - up_write(&s->lock); + unlock_snapshot(s, 0); pe = alloc_pending_exception(s); - down_write(&s->lock); + lock_snapshot(s, 0); if (!s->valid) { free_pending_exception(pe); @@ -1482,7 +1494,7 @@ static int snapshot_map(struct dm_target if (!pe->started) { /* this is protected by snap->lock */ pe->started = 1; - up_write(&s->lock); + unlock_snapshot(s, 0); start_copy(pe); goto out; } @@ -1492,7 +1504,7 @@ static int snapshot_map(struct dm_target } out_unlock: - up_write(&s->lock); + unlock_snapshot(s, 0); out: return r; } @@ -1507,7 +1519,7 @@ static int snapshot_merge_map(struct dm_ chunk = sector_to_chunk(s->store, bio->bi_sector); - down_write(&s->lock); + lock_snapshot(s, 0); /* Full merging snapshots are redirected to the origin */ if (!s->valid) @@ -1539,12 +1551,12 @@ static int snapshot_merge_map(struct dm_ bio->bi_bdev = s->origin->bdev; if (bio_rw(bio) == WRITE) { - up_write(&s->lock); + unlock_snapshot(s, 0); return do_origin(s->origin, bio); } out_unlock: - up_write(&s->lock); + unlock_snapshot(s, 0); return r; } @@ -1566,29 +1578,29 @@ static void snapshot_presuspend(struct d { struct dm_snapshot *s = ti->private; - down_write(&s->lock); + lock_snapshot(s, 0); s->suspended = 1; - up_write(&s->lock); + unlock_snapshot(s, 0); } static void snapshot_resume(struct dm_target *ti) { struct dm_snapshot *s = ti->private; - down_write(&s->lock); + lock_snapshot(s, 0); if (s->handover) { /* Get exception store from another snapshot */ struct dm_snapshot *old_snap = s->handover_snap; BUG_ON(!old_snap); - down_write_nested(&old_snap->lock, SINGLE_DEPTH_NESTING); + lock_snapshot(old_snap, 1); handover_exceptions(old_snap, s); - up_write(&old_snap->lock); + unlock_snapshot(old_snap, 1); } /* An incomplete exception handover is not allowed */ BUG_ON(s->handover || s->handover_snap); s->active = 1; s->suspended = 0; - up_write(&s->lock); + unlock_snapshot(s, 0); } static void snapshot_merge_resume(struct dm_target *ti) @@ -1613,7 +1625,7 @@ static int snapshot_status(struct dm_tar unsigned sz = 0; struct dm_snapshot *snap = ti->private; - down_write(&snap->lock); + lock_snapshot(snap, 0); switch (type) { case STATUSTYPE_INFO: @@ -1649,7 +1661,7 @@ static int snapshot_status(struct dm_tar break; } - up_write(&snap->lock); + unlock_snapshot(snap, 0); return 0; } @@ -1690,7 +1702,7 @@ static int __origin_write(struct list_he if (is_merge(snap->ti)) continue; - down_write(&snap->lock); + lock_snapshot(snap, 0); /* Only deal with valid and active snapshots */ if (!snap->valid || !snap->active) @@ -1717,9 +1729,9 @@ static int __origin_write(struct list_he pe = __lookup_pending_exception(snap, chunk); if (!pe) { - up_write(&snap->lock); + unlock_snapshot(snap, 0); pe = alloc_pending_exception(snap); - down_write(&snap->lock); + lock_snapshot(snap, 0); if (!snap->valid) { free_pending_exception(pe); @@ -1757,7 +1769,7 @@ static int __origin_write(struct list_he } next_snapshot: - up_write(&snap->lock); + unlock_snapshot(snap, 0); } /*