diff options
Diffstat (limited to 'drivers/md/dm.c')
-rw-r--r-- | drivers/md/dm.c | 43 |
1 files changed, 23 insertions, 20 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 83f53a46c2d4..f6b03957efc7 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -1048,20 +1048,16 @@ 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 | int error = -EINVAL; |
1052 | 1052 | ||
1053 | /* Flush I/O to the device. */ | 1053 | /* Flush I/O to the device. */ |
1054 | down_read(&md->lock); | 1054 | down_read(&md->lock); |
1055 | if (test_bit(DMF_BLOCK_IO, &md->flags)) { | 1055 | if (test_bit(DMF_BLOCK_IO, &md->flags)) |
1056 | up_read(&md->lock); | 1056 | goto out_read_unlock; |
1057 | return -EINVAL; | ||
1058 | } | ||
1059 | 1057 | ||
1060 | error = __lock_fs(md); | 1058 | error = __lock_fs(md); |
1061 | if (error) { | 1059 | if (error) |
1062 | up_read(&md->lock); | 1060 | goto out_read_unlock; |
1063 | return error; | ||
1064 | } | ||
1065 | 1061 | ||
1066 | map = dm_get_table(md); | 1062 | map = dm_get_table(md); |
1067 | if (map) | 1063 | if (map) |
@@ -1075,15 +1071,14 @@ int dm_suspend(struct mapped_device *md) | |||
1075 | * If the flag is already set we know another thread is trying to | 1071 | * 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. | 1072 | * suspend as well, so we leave the fs locked for this thread. |
1077 | */ | 1073 | */ |
1074 | error = -EINVAL; | ||
1078 | down_write(&md->lock); | 1075 | down_write(&md->lock); |
1079 | if (test_bit(DMF_BLOCK_IO, &md->flags)) { | 1076 | if (test_and_set_bit(DMF_BLOCK_IO, &md->flags)) { |
1080 | up_write(&md->lock); | ||
1081 | if (map) | 1077 | if (map) |
1082 | dm_table_put(map); | 1078 | dm_table_put(map); |
1083 | return -EINVAL; | 1079 | goto out_write_unlock; |
1084 | } | 1080 | } |
1085 | 1081 | ||
1086 | set_bit(DMF_BLOCK_IO, &md->flags); | ||
1087 | add_wait_queue(&md->wait, &wait); | 1082 | add_wait_queue(&md->wait, &wait); |
1088 | up_write(&md->lock); | 1083 | up_write(&md->lock); |
1089 | 1084 | ||
@@ -1111,13 +1106,9 @@ int dm_suspend(struct mapped_device *md) | |||
1111 | remove_wait_queue(&md->wait, &wait); | 1106 | remove_wait_queue(&md->wait, &wait); |
1112 | 1107 | ||
1113 | /* were we interrupted ? */ | 1108 | /* were we interrupted ? */ |
1114 | if (atomic_read(&md->pending)) { | 1109 | error = -EINTR; |
1115 | /* FIXME Undo the presuspend_targets */ | 1110 | if (atomic_read(&md->pending)) |
1116 | __unlock_fs(md); | 1111 | goto out_unfreeze; |
1117 | clear_bit(DMF_BLOCK_IO, &md->flags); | ||
1118 | up_write(&md->lock); | ||
1119 | return -EINTR; | ||
1120 | } | ||
1121 | 1112 | ||
1122 | set_bit(DMF_SUSPENDED, &md->flags); | 1113 | set_bit(DMF_SUSPENDED, &md->flags); |
1123 | 1114 | ||
@@ -1128,6 +1119,18 @@ int dm_suspend(struct mapped_device *md) | |||
1128 | up_write(&md->lock); | 1119 | up_write(&md->lock); |
1129 | 1120 | ||
1130 | return 0; | 1121 | return 0; |
1122 | |||
1123 | out_unfreeze: | ||
1124 | /* FIXME Undo dm_table_presuspend_targets */ | ||
1125 | __unlock_fs(md); | ||
1126 | clear_bit(DMF_BLOCK_IO, &md->flags); | ||
1127 | out_write_unlock: | ||
1128 | up_write(&md->lock); | ||
1129 | return error; | ||
1130 | |||
1131 | out_read_unlock: | ||
1132 | up_read(&md->lock); | ||
1133 | return error; | ||
1131 | } | 1134 | } |
1132 | 1135 | ||
1133 | int dm_resume(struct mapped_device *md) | 1136 | int dm_resume(struct mapped_device *md) |