diff options
author | Alasdair G Kergon <agk@redhat.com> | 2005-07-29 00:15:57 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-07-29 00:46:03 -0400 |
commit | cf222b3769c3759488579441ab724ed33a2da5f4 (patch) | |
tree | b49e2a731a02cc9a280183232ecad5c165f121eb | |
parent | 8c56ac3f3b12936b03d2626c7572fed5977af515 (diff) |
[PATCH] device-mapper: fix deadlocks in core (prep)
Some code tidy-ups in preparation for the next patches. Change
dm_table_pre/postsuspend_targets to accept NULL. Use dm_suspended()
throughout.
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>
-rw-r--r-- | drivers/md/dm-table.c | 6 | ||||
-rw-r--r-- | drivers/md/dm.c | 61 |
2 files changed, 39 insertions, 28 deletions
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index a5a4c0ed8a14..a6d3baa46f61 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c | |||
@@ -869,11 +869,17 @@ static void suspend_targets(struct dm_table *t, unsigned postsuspend) | |||
869 | 869 | ||
870 | void dm_table_presuspend_targets(struct dm_table *t) | 870 | void dm_table_presuspend_targets(struct dm_table *t) |
871 | { | 871 | { |
872 | if (!t) | ||
873 | return; | ||
874 | |||
872 | return suspend_targets(t, 0); | 875 | return suspend_targets(t, 0); |
873 | } | 876 | } |
874 | 877 | ||
875 | void dm_table_postsuspend_targets(struct dm_table *t) | 878 | void dm_table_postsuspend_targets(struct dm_table *t) |
876 | { | 879 | { |
880 | if (!t) | ||
881 | return; | ||
882 | |||
877 | return suspend_targets(t, 1); | 883 | return suspend_targets(t, 1); |
878 | } | 884 | } |
879 | 885 | ||
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 54fabbf06678..f0cd8ea327d3 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -610,7 +610,7 @@ static int dm_flush_all(request_queue_t *q, struct gendisk *disk, | |||
610 | int ret = -ENXIO; | 610 | int ret = -ENXIO; |
611 | 611 | ||
612 | if (map) { | 612 | if (map) { |
613 | ret = dm_table_flush_all(md->map); | 613 | ret = dm_table_flush_all(map); |
614 | dm_table_put(map); | 614 | dm_table_put(map); |
615 | } | 615 | } |
616 | 616 | ||
@@ -854,7 +854,7 @@ static int __bind(struct mapped_device *md, struct dm_table *t) | |||
854 | write_unlock(&md->map_lock); | 854 | write_unlock(&md->map_lock); |
855 | 855 | ||
856 | dm_table_get(t); | 856 | dm_table_get(t); |
857 | dm_table_event_callback(md->map, event_callback, md); | 857 | dm_table_event_callback(t, event_callback, md); |
858 | dm_table_set_restrictions(t, q); | 858 | dm_table_set_restrictions(t, q); |
859 | return 0; | 859 | return 0; |
860 | } | 860 | } |
@@ -935,7 +935,7 @@ void dm_put(struct mapped_device *md) | |||
935 | struct dm_table *map = dm_get_table(md); | 935 | struct dm_table *map = dm_get_table(md); |
936 | 936 | ||
937 | if (atomic_dec_and_test(&md->holders)) { | 937 | if (atomic_dec_and_test(&md->holders)) { |
938 | if (!test_bit(DMF_SUSPENDED, &md->flags) && map) { | 938 | if (!dm_suspended(md)) { |
939 | dm_table_presuspend_targets(map); | 939 | dm_table_presuspend_targets(map); |
940 | dm_table_postsuspend_targets(map); | 940 | dm_table_postsuspend_targets(map); |
941 | } | 941 | } |
@@ -971,7 +971,7 @@ int dm_swap_table(struct mapped_device *md, struct dm_table *table) | |||
971 | down_write(&md->lock); | 971 | down_write(&md->lock); |
972 | 972 | ||
973 | /* device must be suspended */ | 973 | /* device must be suspended */ |
974 | if (!test_bit(DMF_SUSPENDED, &md->flags)) | 974 | if (!dm_suspended(md)) |
975 | goto out; | 975 | goto out; |
976 | 976 | ||
977 | __unbind(md); | 977 | __unbind(md); |
@@ -988,7 +988,7 @@ out: | |||
988 | */ | 988 | */ |
989 | static int __lock_fs(struct mapped_device *md) | 989 | static int __lock_fs(struct mapped_device *md) |
990 | { | 990 | { |
991 | int error = -ENOMEM; | 991 | int r = -ENOMEM; |
992 | 992 | ||
993 | if (test_and_set_bit(DMF_FS_LOCKED, &md->flags)) | 993 | if (test_and_set_bit(DMF_FS_LOCKED, &md->flags)) |
994 | return 0; | 994 | return 0; |
@@ -1003,7 +1003,7 @@ static int __lock_fs(struct mapped_device *md) | |||
1003 | 1003 | ||
1004 | md->frozen_sb = freeze_bdev(md->frozen_bdev); | 1004 | md->frozen_sb = freeze_bdev(md->frozen_bdev); |
1005 | if (IS_ERR(md->frozen_sb)) { | 1005 | if (IS_ERR(md->frozen_sb)) { |
1006 | error = PTR_ERR(md->frozen_sb); | 1006 | r = PTR_ERR(md->frozen_sb); |
1007 | goto out_bdput; | 1007 | goto out_bdput; |
1008 | } | 1008 | } |
1009 | 1009 | ||
@@ -1019,7 +1019,7 @@ out_bdput: | |||
1019 | md->frozen_bdev = NULL; | 1019 | md->frozen_bdev = NULL; |
1020 | out: | 1020 | out: |
1021 | clear_bit(DMF_FS_LOCKED, &md->flags); | 1021 | clear_bit(DMF_FS_LOCKED, &md->flags); |
1022 | return error; | 1022 | return r; |
1023 | } | 1023 | } |
1024 | 1024 | ||
1025 | static void __unlock_fs(struct mapped_device *md) | 1025 | static void __unlock_fs(struct mapped_device *md) |
@@ -1045,20 +1045,20 @@ int dm_suspend(struct mapped_device *md) | |||
1045 | { | 1045 | { |
1046 | struct dm_table *map; | 1046 | struct dm_table *map; |
1047 | DECLARE_WAITQUEUE(wait, current); | 1047 | DECLARE_WAITQUEUE(wait, current); |
1048 | int error = -EINVAL; | 1048 | int r = -EINVAL; |
1049 | 1049 | ||
1050 | /* Flush I/O to the device. */ | ||
1051 | down_read(&md->lock); | 1050 | down_read(&md->lock); |
1052 | if (test_bit(DMF_BLOCK_IO, &md->flags)) | 1051 | if (test_bit(DMF_BLOCK_IO, &md->flags)) |
1053 | goto out_read_unlock; | 1052 | goto out_read_unlock; |
1054 | 1053 | ||
1055 | map = dm_get_table(md); | 1054 | map = dm_get_table(md); |
1056 | if (map) | ||
1057 | /* This does not get reverted if there's an error later. */ | ||
1058 | dm_table_presuspend_targets(map); | ||
1059 | 1055 | ||
1060 | error = __lock_fs(md); | 1056 | /* This does not get reverted if there's an error later. */ |
1061 | if (error) { | 1057 | dm_table_presuspend_targets(map); |
1058 | |||
1059 | /* Flush I/O to the device. */ | ||
1060 | r = __lock_fs(md); | ||
1061 | if (r) { | ||
1062 | dm_table_put(map); | 1062 | dm_table_put(map); |
1063 | goto out_read_unlock; | 1063 | goto out_read_unlock; |
1064 | } | 1064 | } |
@@ -1071,7 +1071,7 @@ int dm_suspend(struct mapped_device *md) | |||
1071 | * 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 |
1072 | * 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. |
1073 | */ | 1073 | */ |
1074 | error = -EINVAL; | 1074 | r = -EINVAL; |
1075 | down_write(&md->lock); | 1075 | down_write(&md->lock); |
1076 | if (test_and_set_bit(DMF_BLOCK_IO, &md->flags)) { | 1076 | if (test_and_set_bit(DMF_BLOCK_IO, &md->flags)) { |
1077 | if (map) | 1077 | if (map) |
@@ -1106,15 +1106,14 @@ int dm_suspend(struct mapped_device *md) | |||
1106 | remove_wait_queue(&md->wait, &wait); | 1106 | remove_wait_queue(&md->wait, &wait); |
1107 | 1107 | ||
1108 | /* were we interrupted ? */ | 1108 | /* were we interrupted ? */ |
1109 | error = -EINTR; | 1109 | r = -EINTR; |
1110 | if (atomic_read(&md->pending)) | 1110 | if (atomic_read(&md->pending)) |
1111 | goto out_unfreeze; | 1111 | goto out_unfreeze; |
1112 | 1112 | ||
1113 | set_bit(DMF_SUSPENDED, &md->flags); | 1113 | set_bit(DMF_SUSPENDED, &md->flags); |
1114 | 1114 | ||
1115 | map = dm_get_table(md); | 1115 | map = dm_get_table(md); |
1116 | if (map) | 1116 | dm_table_postsuspend_targets(map); |
1117 | dm_table_postsuspend_targets(map); | ||
1118 | dm_table_put(map); | 1117 | dm_table_put(map); |
1119 | up_write(&md->lock); | 1118 | up_write(&md->lock); |
1120 | 1119 | ||
@@ -1125,25 +1124,29 @@ out_unfreeze: | |||
1125 | clear_bit(DMF_BLOCK_IO, &md->flags); | 1124 | clear_bit(DMF_BLOCK_IO, &md->flags); |
1126 | out_write_unlock: | 1125 | out_write_unlock: |
1127 | up_write(&md->lock); | 1126 | up_write(&md->lock); |
1128 | return error; | 1127 | return r; |
1129 | 1128 | ||
1130 | out_read_unlock: | 1129 | out_read_unlock: |
1131 | up_read(&md->lock); | 1130 | up_read(&md->lock); |
1132 | return error; | 1131 | return r; |
1133 | } | 1132 | } |
1134 | 1133 | ||
1135 | int dm_resume(struct mapped_device *md) | 1134 | int dm_resume(struct mapped_device *md) |
1136 | { | 1135 | { |
1136 | int r = -EINVAL; | ||
1137 | struct bio *def; | 1137 | struct bio *def; |
1138 | struct dm_table *map = dm_get_table(md); | 1138 | struct dm_table *map = NULL; |
1139 | 1139 | ||
1140 | down_write(&md->lock); | 1140 | down_write(&md->lock); |
1141 | if (!map || | 1141 | if (!dm_suspended(md)) { |
1142 | !test_bit(DMF_SUSPENDED, &md->flags) || | ||
1143 | !dm_table_get_size(map)) { | ||
1144 | up_write(&md->lock); | 1142 | up_write(&md->lock); |
1145 | dm_table_put(map); | 1143 | goto out; |
1146 | return -EINVAL; | 1144 | } |
1145 | |||
1146 | map = dm_get_table(md); | ||
1147 | if (!map || !dm_table_get_size(map)) { | ||
1148 | up_write(&md->lock); | ||
1149 | goto out; | ||
1147 | } | 1150 | } |
1148 | 1151 | ||
1149 | dm_table_resume_targets(map); | 1152 | dm_table_resume_targets(map); |
@@ -1155,9 +1158,11 @@ int dm_resume(struct mapped_device *md) | |||
1155 | up_write(&md->lock); | 1158 | up_write(&md->lock); |
1156 | __unlock_fs(md); | 1159 | __unlock_fs(md); |
1157 | dm_table_unplug_all(map); | 1160 | dm_table_unplug_all(map); |
1158 | dm_table_put(map); | ||
1159 | 1161 | ||
1160 | return 0; | 1162 | r = 0; |
1163 | out: | ||
1164 | dm_table_put(map); | ||
1165 | return r; | ||
1161 | } | 1166 | } |
1162 | 1167 | ||
1163 | /*----------------------------------------------------------------- | 1168 | /*----------------------------------------------------------------- |