aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/persistent-data/dm-space-map-checker.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/persistent-data/dm-space-map-checker.c')
-rw-r--r--drivers/md/persistent-data/dm-space-map-checker.c54
1 files changed, 31 insertions, 23 deletions
diff --git a/drivers/md/persistent-data/dm-space-map-checker.c b/drivers/md/persistent-data/dm-space-map-checker.c
index 50ed53bf4aa2..fc90c11620ad 100644
--- a/drivers/md/persistent-data/dm-space-map-checker.c
+++ b/drivers/md/persistent-data/dm-space-map-checker.c
@@ -8,6 +8,7 @@
8 8
9#include <linux/device-mapper.h> 9#include <linux/device-mapper.h>
10#include <linux/export.h> 10#include <linux/export.h>
11#include <linux/vmalloc.h>
11 12
12#ifdef CONFIG_DM_DEBUG_SPACE_MAPS 13#ifdef CONFIG_DM_DEBUG_SPACE_MAPS
13 14
@@ -89,13 +90,23 @@ static int ca_create(struct count_array *ca, struct dm_space_map *sm)
89 90
90 ca->nr = nr_blocks; 91 ca->nr = nr_blocks;
91 ca->nr_free = nr_blocks; 92 ca->nr_free = nr_blocks;
92 ca->counts = kzalloc(sizeof(*ca->counts) * nr_blocks, GFP_KERNEL); 93
93 if (!ca->counts) 94 if (!nr_blocks)
94 return -ENOMEM; 95 ca->counts = NULL;
96 else {
97 ca->counts = vzalloc(sizeof(*ca->counts) * nr_blocks);
98 if (!ca->counts)
99 return -ENOMEM;
100 }
95 101
96 return 0; 102 return 0;
97} 103}
98 104
105static void ca_destroy(struct count_array *ca)
106{
107 vfree(ca->counts);
108}
109
99static int ca_load(struct count_array *ca, struct dm_space_map *sm) 110static int ca_load(struct count_array *ca, struct dm_space_map *sm)
100{ 111{
101 int r; 112 int r;
@@ -126,12 +137,14 @@ static int ca_load(struct count_array *ca, struct dm_space_map *sm)
126static int ca_extend(struct count_array *ca, dm_block_t extra_blocks) 137static int ca_extend(struct count_array *ca, dm_block_t extra_blocks)
127{ 138{
128 dm_block_t nr_blocks = ca->nr + extra_blocks; 139 dm_block_t nr_blocks = ca->nr + extra_blocks;
129 uint32_t *counts = kzalloc(sizeof(*counts) * nr_blocks, GFP_KERNEL); 140 uint32_t *counts = vzalloc(sizeof(*counts) * nr_blocks);
130 if (!counts) 141 if (!counts)
131 return -ENOMEM; 142 return -ENOMEM;
132 143
133 memcpy(counts, ca->counts, sizeof(*counts) * ca->nr); 144 if (ca->counts) {
134 kfree(ca->counts); 145 memcpy(counts, ca->counts, sizeof(*counts) * ca->nr);
146 ca_destroy(ca);
147 }
135 ca->nr = nr_blocks; 148 ca->nr = nr_blocks;
136 ca->nr_free += extra_blocks; 149 ca->nr_free += extra_blocks;
137 ca->counts = counts; 150 ca->counts = counts;
@@ -151,11 +164,6 @@ static int ca_commit(struct count_array *old, struct count_array *new)
151 return 0; 164 return 0;
152} 165}
153 166
154static void ca_destroy(struct count_array *ca)
155{
156 kfree(ca->counts);
157}
158
159/*----------------------------------------------------------------*/ 167/*----------------------------------------------------------------*/
160 168
161struct sm_checker { 169struct sm_checker {
@@ -343,25 +351,25 @@ struct dm_space_map *dm_sm_checker_create(struct dm_space_map *sm)
343 int r; 351 int r;
344 struct sm_checker *smc; 352 struct sm_checker *smc;
345 353
346 if (!sm) 354 if (IS_ERR_OR_NULL(sm))
347 return NULL; 355 return ERR_PTR(-EINVAL);
348 356
349 smc = kmalloc(sizeof(*smc), GFP_KERNEL); 357 smc = kmalloc(sizeof(*smc), GFP_KERNEL);
350 if (!smc) 358 if (!smc)
351 return NULL; 359 return ERR_PTR(-ENOMEM);
352 360
353 memcpy(&smc->sm, &ops_, sizeof(smc->sm)); 361 memcpy(&smc->sm, &ops_, sizeof(smc->sm));
354 r = ca_create(&smc->old_counts, sm); 362 r = ca_create(&smc->old_counts, sm);
355 if (r) { 363 if (r) {
356 kfree(smc); 364 kfree(smc);
357 return NULL; 365 return ERR_PTR(r);
358 } 366 }
359 367
360 r = ca_create(&smc->counts, sm); 368 r = ca_create(&smc->counts, sm);
361 if (r) { 369 if (r) {
362 ca_destroy(&smc->old_counts); 370 ca_destroy(&smc->old_counts);
363 kfree(smc); 371 kfree(smc);
364 return NULL; 372 return ERR_PTR(r);
365 } 373 }
366 374
367 smc->real_sm = sm; 375 smc->real_sm = sm;
@@ -371,7 +379,7 @@ struct dm_space_map *dm_sm_checker_create(struct dm_space_map *sm)
371 ca_destroy(&smc->counts); 379 ca_destroy(&smc->counts);
372 ca_destroy(&smc->old_counts); 380 ca_destroy(&smc->old_counts);
373 kfree(smc); 381 kfree(smc);
374 return NULL; 382 return ERR_PTR(r);
375 } 383 }
376 384
377 r = ca_commit(&smc->old_counts, &smc->counts); 385 r = ca_commit(&smc->old_counts, &smc->counts);
@@ -379,7 +387,7 @@ struct dm_space_map *dm_sm_checker_create(struct dm_space_map *sm)
379 ca_destroy(&smc->counts); 387 ca_destroy(&smc->counts);
380 ca_destroy(&smc->old_counts); 388 ca_destroy(&smc->old_counts);
381 kfree(smc); 389 kfree(smc);
382 return NULL; 390 return ERR_PTR(r);
383 } 391 }
384 392
385 return &smc->sm; 393 return &smc->sm;
@@ -391,25 +399,25 @@ struct dm_space_map *dm_sm_checker_create_fresh(struct dm_space_map *sm)
391 int r; 399 int r;
392 struct sm_checker *smc; 400 struct sm_checker *smc;
393 401
394 if (!sm) 402 if (IS_ERR_OR_NULL(sm))
395 return NULL; 403 return ERR_PTR(-EINVAL);
396 404
397 smc = kmalloc(sizeof(*smc), GFP_KERNEL); 405 smc = kmalloc(sizeof(*smc), GFP_KERNEL);
398 if (!smc) 406 if (!smc)
399 return NULL; 407 return ERR_PTR(-ENOMEM);
400 408
401 memcpy(&smc->sm, &ops_, sizeof(smc->sm)); 409 memcpy(&smc->sm, &ops_, sizeof(smc->sm));
402 r = ca_create(&smc->old_counts, sm); 410 r = ca_create(&smc->old_counts, sm);
403 if (r) { 411 if (r) {
404 kfree(smc); 412 kfree(smc);
405 return NULL; 413 return ERR_PTR(r);
406 } 414 }
407 415
408 r = ca_create(&smc->counts, sm); 416 r = ca_create(&smc->counts, sm);
409 if (r) { 417 if (r) {
410 ca_destroy(&smc->old_counts); 418 ca_destroy(&smc->old_counts);
411 kfree(smc); 419 kfree(smc);
412 return NULL; 420 return ERR_PTR(r);
413 } 421 }
414 422
415 smc->real_sm = sm; 423 smc->real_sm = sm;