summary refs log tree commit diff
path: root/drivers/md/dm.c
diff options
context:
space:
mode:
authorAlasdair G Kergon <agk@redhat.com>2005-07-12 15:53:03 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2005-07-12 16:19:10 -0700
commit436d41087d047b61f8ab0604dc74fff3240a8933 (patch)
tree46bab3a0cf02a7514b4faa5470a76326e6f8bc72 /drivers/md/dm.c
parenta044d016896d2717694003f00d31a98194077511 (diff)
downloadlinux-436d41087d047b61f8ab0604dc74fff3240a8933.tar.gz
[PATCH] device-mapper multipath: Avoid possible suspension deadlock
To avoid deadlock when suspending a multipath device after all its paths have
failed, stop queueing any I/O that is about to fail *before* calling
freeze_bdev instead of after.

Instead of setting a multipath 'suspended' flag which would have to be reset
if an error occurs during the process, save the previous queueing state and
leave userspace to restore if it wishes.

Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/md/dm.c')
-rw-r--r--drivers/md/dm.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 5d40555b42ba..bb3ad79c14d7 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1055,14 +1055,17 @@ int dm_suspend(struct mapped_device *md)
 	if (test_bit(DMF_BLOCK_IO, &md->flags))
 		goto out_read_unlock;
 
-	error = __lock_fs(md);
-	if (error)
-		goto out_read_unlock;
-
 	map = dm_get_table(md);
 	if (map)
+		/* This does not get reverted if there's an error later. */
 		dm_table_presuspend_targets(map);
 
+	error = __lock_fs(md);
+	if (error) {
+		dm_table_put(map);
+		goto out_read_unlock;
+	}
+
 	up_read(&md->lock);
 
 	/*
@@ -1121,7 +1124,6 @@ int dm_suspend(struct mapped_device *md)
 	return 0;
 
 out_unfreeze:
-	/* FIXME Undo dm_table_presuspend_targets */
 	__unlock_fs(md);
 	clear_bit(DMF_BLOCK_IO, &md->flags);
 out_write_unlock: