diff options
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/dm.c | 22 |
1 files changed, 14 insertions, 8 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 9687a084b5f..83f53a46c2d 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -1048,6 +1048,7 @@ int dm_suspend(struct mapped_device *md) | |||
1048 | { | 1048 | { |
1049 | struct dm_table *map; | 1049 | struct dm_table *map; |
1050 | DECLARE_WAITQUEUE(wait, current); | 1050 | DECLARE_WAITQUEUE(wait, current); |
1051 | int error; | ||
1051 | 1052 | ||
1052 | /* Flush I/O to the device. */ | 1053 | /* Flush I/O to the device. */ |
1053 | down_read(&md->lock); | 1054 | down_read(&md->lock); |
@@ -1056,25 +1057,29 @@ int dm_suspend(struct mapped_device *md) | |||
1056 | return -EINVAL; | 1057 | return -EINVAL; |
1057 | } | 1058 | } |
1058 | 1059 | ||
1060 | error = __lock_fs(md); | ||
1061 | if (error) { | ||
1062 | up_read(&md->lock); | ||
1063 | return error; | ||
1064 | } | ||
1065 | |||
1059 | map = dm_get_table(md); | 1066 | map = dm_get_table(md); |
1060 | if (map) | 1067 | if (map) |
1061 | dm_table_presuspend_targets(map); | 1068 | dm_table_presuspend_targets(map); |
1062 | __lock_fs(md); | ||
1063 | 1069 | ||
1064 | up_read(&md->lock); | 1070 | up_read(&md->lock); |
1065 | 1071 | ||
1066 | /* | 1072 | /* |
1067 | * First we set the BLOCK_IO flag so no more ios will be | 1073 | * First we set the BLOCK_IO flag so no more ios will be mapped. |
1068 | * mapped. | 1074 | * |
1075 | * If the flag is already set we know another thread is trying to | ||
1076 | * suspend as well, so we leave the fs locked for this thread. | ||
1069 | */ | 1077 | */ |
1070 | down_write(&md->lock); | 1078 | down_write(&md->lock); |
1071 | if (test_bit(DMF_BLOCK_IO, &md->flags)) { | 1079 | if (test_bit(DMF_BLOCK_IO, &md->flags)) { |
1072 | /* | ||
1073 | * If we get here we know another thread is | ||
1074 | * trying to suspend as well, so we leave the fs | ||
1075 | * locked for this thread. | ||
1076 | */ | ||
1077 | up_write(&md->lock); | 1080 | up_write(&md->lock); |
1081 | if (map) | ||
1082 | dm_table_put(map); | ||
1078 | return -EINVAL; | 1083 | return -EINVAL; |
1079 | } | 1084 | } |
1080 | 1085 | ||
@@ -1107,6 +1112,7 @@ int dm_suspend(struct mapped_device *md) | |||
1107 | 1112 | ||
1108 | /* were we interrupted ? */ | 1113 | /* were we interrupted ? */ |
1109 | if (atomic_read(&md->pending)) { | 1114 | if (atomic_read(&md->pending)) { |
1115 | /* FIXME Undo the presuspend_targets */ | ||
1110 | __unlock_fs(md); | 1116 | __unlock_fs(md); |
1111 | clear_bit(DMF_BLOCK_IO, &md->flags); | 1117 | clear_bit(DMF_BLOCK_IO, &md->flags); |
1112 | up_write(&md->lock); | 1118 | up_write(&md->lock); |