aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorAlasdair G Kergon <agk@redhat.com>2005-07-29 00:15:57 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-07-29 00:46:03 -0400
commitcf222b3769c3759488579441ab724ed33a2da5f4 (patch)
treeb49e2a731a02cc9a280183232ecad5c165f121eb /drivers/md
parent8c56ac3f3b12936b03d2626c7572fed5977af515 (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>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/dm-table.c6
-rw-r--r--drivers/md/dm.c61
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
870void dm_table_presuspend_targets(struct dm_table *t) 870void 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
875void dm_table_postsuspend_targets(struct dm_table *t) 878void 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 */
989static int __lock_fs(struct mapped_device *md) 989static 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;
1020out: 1020out:
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
1025static void __unlock_fs(struct mapped_device *md) 1025static 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);
1126out_write_unlock: 1125out_write_unlock:
1127 up_write(&md->lock); 1126 up_write(&md->lock);
1128 return error; 1127 return r;
1129 1128
1130out_read_unlock: 1129out_read_unlock:
1131 up_read(&md->lock); 1130 up_read(&md->lock);
1132 return error; 1131 return r;
1133} 1132}
1134 1133
1135int dm_resume(struct mapped_device *md) 1134int 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;
1163out:
1164 dm_table_put(map);
1165 return r;
1161} 1166}
1162 1167
1163/*----------------------------------------------------------------- 1168/*-----------------------------------------------------------------