diff mbox

Re: dm snapshot: allow live exception store handover between tables

Message ID 20091106192620.GD13427@redhat.com (mailing list archive)
State Superseded, archived
Headers show

Commit Message

Mike Snitzer Nov. 6, 2009, 7:26 p.m. UTC
None
diff mbox

Patch

diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index e5acff4..1ba1861 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -82,9 +82,10 @@  struct dm_snapshot {
 	 *
 	 * 'is_handover_destination' is set in snapshot_ctr if an existing
 	 * snapshot has the same cow device. The handover is performed,
-	 * and 'is_handover_destination' is cleared, when either of the
+	 * and 'is_handover_destination' is cleared, when one of the
 	 * following occurs:
 	 * - src (old) snapshot, that is handing over, is destructed
+	 * - src (old) snapshot, that is handing over, is resumed
 	 * - dest (new) snapshot, that is accepting the handover, is resumed
 	 */
 	int is_handover_destination;
@@ -1379,23 +1380,28 @@  static void snapshot_presuspend(struct dm_target *ti)
 static void snapshot_resume(struct dm_target *ti)
 {
 	struct dm_snapshot *s = ti->private;
-	struct dm_snapshot *old_snap, *new_snap = NULL;
+	struct dm_snapshot *lock_snap, *old_snap, *new_snap = NULL;
 
 	down_write(&s->lock);
 	if (s->handover_snap) {
-		if (!s->is_handover_destination) {
-			DMERR("Unable to handover exceptions to "
-			      "another snapshot on resume.");
-			goto out;
-		}
-		/* Get exception store from another snapshot */
+		/*
+		 * Initially assumes this snapshot will get
+		 * exception store from another snapshot
+		 */
 		old_snap = s->handover_snap;
 		new_snap = s;
+		lock_snap = old_snap;
 
-		down_write_nested(&old_snap->lock,
+		if (!s->is_handover_destination) {
+			/* Handover exceptions to another snapshot */
+			old_snap = s;
+			new_snap = s->handover_snap;
+			lock_snap = new_snap;
+		}
+		down_write_nested(&lock_snap->lock,
 				  SINGLE_DEPTH_NESTING);
 		handover_exceptions(old_snap, new_snap);
-		up_write(&old_snap->lock);
+		up_write(&lock_snap->lock);
 	}
 	/* An incomplete exception handover is not allowed */
 	BUG_ON(s->handover_snap);