From 436d41087d047b61f8ab0604dc74fff3240a8933 Mon Sep 17 00:00:00 2001 From: Alasdair G Kergon Date: Tue, 12 Jul 2005 15:53:03 -0700 Subject: [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 Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/md/dm.c') diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 5d40555b42b..bb3ad79c14d 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: -- cgit v1.2.3