diff options
author | Dmitry Monakhov <dmonakhov@openvz.org> | 2007-10-19 17:38:39 -0400 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2007-10-19 21:01:01 -0400 |
commit | a72cf737e09da409e047863e38410930dae5fe05 (patch) | |
tree | 66a7b5e897e6625e1690ea42b7944e17f8d3161b | |
parent | 815f9e32709b014a459919176a4f0feebd42731e (diff) |
dm raid1: fix leakage
Add missing 'dm_io_client_destroy' to alloc_context error path.
Reorganize mirror constructor error path in order to prevent
workqueue leakage.
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
-rw-r--r-- | drivers/md/dm-raid1.c | 28 |
1 files changed, 15 insertions, 13 deletions
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index d09ff15490a5..6f60f307fae2 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c | |||
@@ -974,6 +974,7 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors, | |||
974 | 974 | ||
975 | if (rh_init(&ms->rh, ms, dl, region_size, ms->nr_regions)) { | 975 | if (rh_init(&ms->rh, ms, dl, region_size, ms->nr_regions)) { |
976 | ti->error = "Error creating dirty region hash"; | 976 | ti->error = "Error creating dirty region hash"; |
977 | dm_io_client_destroy(ms->io_client); | ||
977 | kfree(ms); | 978 | kfree(ms); |
978 | return NULL; | 979 | return NULL; |
979 | } | 980 | } |
@@ -1163,16 +1164,14 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
1163 | ms->kmirrord_wq = create_singlethread_workqueue("kmirrord"); | 1164 | ms->kmirrord_wq = create_singlethread_workqueue("kmirrord"); |
1164 | if (!ms->kmirrord_wq) { | 1165 | if (!ms->kmirrord_wq) { |
1165 | DMERR("couldn't start kmirrord"); | 1166 | DMERR("couldn't start kmirrord"); |
1166 | free_context(ms, ti, m); | 1167 | r = -ENOMEM; |
1167 | return -ENOMEM; | 1168 | goto err_free_context; |
1168 | } | 1169 | } |
1169 | INIT_WORK(&ms->kmirrord_work, do_mirror); | 1170 | INIT_WORK(&ms->kmirrord_work, do_mirror); |
1170 | 1171 | ||
1171 | r = parse_features(ms, argc, argv, &args_used); | 1172 | r = parse_features(ms, argc, argv, &args_used); |
1172 | if (r) { | 1173 | if (r) |
1173 | free_context(ms, ti, ms->nr_mirrors); | 1174 | goto err_destroy_wq; |
1174 | return r; | ||
1175 | } | ||
1176 | 1175 | ||
1177 | argv += args_used; | 1176 | argv += args_used; |
1178 | argc -= args_used; | 1177 | argc -= args_used; |
@@ -1188,19 +1187,22 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
1188 | 1187 | ||
1189 | if (argc) { | 1188 | if (argc) { |
1190 | ti->error = "Too many mirror arguments"; | 1189 | ti->error = "Too many mirror arguments"; |
1191 | free_context(ms, ti, ms->nr_mirrors); | 1190 | r = -EINVAL; |
1192 | return -EINVAL; | 1191 | goto err_destroy_wq; |
1193 | } | 1192 | } |
1194 | 1193 | ||
1195 | r = kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client); | 1194 | r = kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client); |
1196 | if (r) { | 1195 | if (r) |
1197 | destroy_workqueue(ms->kmirrord_wq); | 1196 | goto err_destroy_wq; |
1198 | free_context(ms, ti, ms->nr_mirrors); | ||
1199 | return r; | ||
1200 | } | ||
1201 | 1197 | ||
1202 | wake(ms); | 1198 | wake(ms); |
1203 | return 0; | 1199 | return 0; |
1200 | |||
1201 | err_destroy_wq: | ||
1202 | destroy_workqueue(ms->kmirrord_wq); | ||
1203 | err_free_context: | ||
1204 | free_context(ms, ti, ms->nr_mirrors); | ||
1205 | return r; | ||
1204 | } | 1206 | } |
1205 | 1207 | ||
1206 | static void mirror_dtr(struct dm_target *ti) | 1208 | static void mirror_dtr(struct dm_target *ti) |