diff options
-rw-r--r-- | drivers/md/Kconfig | 9 | ||||
-rw-r--r-- | drivers/md/persistent-data/Makefile | 1 | ||||
-rw-r--r-- | drivers/md/persistent-data/dm-space-map-checker.c | 446 | ||||
-rw-r--r-- | drivers/md/persistent-data/dm-space-map-checker.h | 26 | ||||
-rw-r--r-- | drivers/md/persistent-data/dm-space-map-disk.c | 34 | ||||
-rw-r--r-- | drivers/md/persistent-data/dm-transaction-manager.c | 29 |
6 files changed, 11 insertions, 534 deletions
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index 10f122a3a856..1eee45b69b71 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig | |||
@@ -260,15 +260,6 @@ config DM_DEBUG_BLOCK_STACK_TRACING | |||
260 | 260 | ||
261 | If unsure, say N. | 261 | If unsure, say N. |
262 | 262 | ||
263 | config DM_DEBUG_SPACE_MAPS | ||
264 | boolean "Extra validation for thin provisioning space maps" | ||
265 | depends on DM_THIN_PROVISIONING | ||
266 | ---help--- | ||
267 | Enable this for messages that may help debug problems with the | ||
268 | space maps used by thin provisioning. | ||
269 | |||
270 | If unsure, say N. | ||
271 | |||
272 | config DM_MIRROR | 263 | config DM_MIRROR |
273 | tristate "Mirror target" | 264 | tristate "Mirror target" |
274 | depends on BLK_DEV_DM | 265 | depends on BLK_DEV_DM |
diff --git a/drivers/md/persistent-data/Makefile b/drivers/md/persistent-data/Makefile index cfa95f662230..d8e7cb767c1e 100644 --- a/drivers/md/persistent-data/Makefile +++ b/drivers/md/persistent-data/Makefile | |||
@@ -1,7 +1,6 @@ | |||
1 | obj-$(CONFIG_DM_PERSISTENT_DATA) += dm-persistent-data.o | 1 | obj-$(CONFIG_DM_PERSISTENT_DATA) += dm-persistent-data.o |
2 | dm-persistent-data-objs := \ | 2 | dm-persistent-data-objs := \ |
3 | dm-block-manager.o \ | 3 | dm-block-manager.o \ |
4 | dm-space-map-checker.o \ | ||
5 | dm-space-map-common.o \ | 4 | dm-space-map-common.o \ |
6 | dm-space-map-disk.o \ | 5 | dm-space-map-disk.o \ |
7 | dm-space-map-metadata.o \ | 6 | dm-space-map-metadata.o \ |
diff --git a/drivers/md/persistent-data/dm-space-map-checker.c b/drivers/md/persistent-data/dm-space-map-checker.c deleted file mode 100644 index fc90c11620ad..000000000000 --- a/drivers/md/persistent-data/dm-space-map-checker.c +++ /dev/null | |||
@@ -1,446 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Red Hat, Inc. | ||
3 | * | ||
4 | * This file is released under the GPL. | ||
5 | */ | ||
6 | |||
7 | #include "dm-space-map-checker.h" | ||
8 | |||
9 | #include <linux/device-mapper.h> | ||
10 | #include <linux/export.h> | ||
11 | #include <linux/vmalloc.h> | ||
12 | |||
13 | #ifdef CONFIG_DM_DEBUG_SPACE_MAPS | ||
14 | |||
15 | #define DM_MSG_PREFIX "space map checker" | ||
16 | |||
17 | /*----------------------------------------------------------------*/ | ||
18 | |||
19 | struct count_array { | ||
20 | dm_block_t nr; | ||
21 | dm_block_t nr_free; | ||
22 | |||
23 | uint32_t *counts; | ||
24 | }; | ||
25 | |||
26 | static int ca_get_count(struct count_array *ca, dm_block_t b, uint32_t *count) | ||
27 | { | ||
28 | if (b >= ca->nr) | ||
29 | return -EINVAL; | ||
30 | |||
31 | *count = ca->counts[b]; | ||
32 | return 0; | ||
33 | } | ||
34 | |||
35 | static int ca_count_more_than_one(struct count_array *ca, dm_block_t b, int *r) | ||
36 | { | ||
37 | if (b >= ca->nr) | ||
38 | return -EINVAL; | ||
39 | |||
40 | *r = ca->counts[b] > 1; | ||
41 | return 0; | ||
42 | } | ||
43 | |||
44 | static int ca_set_count(struct count_array *ca, dm_block_t b, uint32_t count) | ||
45 | { | ||
46 | uint32_t old_count; | ||
47 | |||
48 | if (b >= ca->nr) | ||
49 | return -EINVAL; | ||
50 | |||
51 | old_count = ca->counts[b]; | ||
52 | |||
53 | if (!count && old_count) | ||
54 | ca->nr_free++; | ||
55 | |||
56 | else if (count && !old_count) | ||
57 | ca->nr_free--; | ||
58 | |||
59 | ca->counts[b] = count; | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | static int ca_inc_block(struct count_array *ca, dm_block_t b) | ||
64 | { | ||
65 | if (b >= ca->nr) | ||
66 | return -EINVAL; | ||
67 | |||
68 | ca_set_count(ca, b, ca->counts[b] + 1); | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static int ca_dec_block(struct count_array *ca, dm_block_t b) | ||
73 | { | ||
74 | if (b >= ca->nr) | ||
75 | return -EINVAL; | ||
76 | |||
77 | BUG_ON(ca->counts[b] == 0); | ||
78 | ca_set_count(ca, b, ca->counts[b] - 1); | ||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static int ca_create(struct count_array *ca, struct dm_space_map *sm) | ||
83 | { | ||
84 | int r; | ||
85 | dm_block_t nr_blocks; | ||
86 | |||
87 | r = dm_sm_get_nr_blocks(sm, &nr_blocks); | ||
88 | if (r) | ||
89 | return r; | ||
90 | |||
91 | ca->nr = nr_blocks; | ||
92 | ca->nr_free = nr_blocks; | ||
93 | |||
94 | if (!nr_blocks) | ||
95 | ca->counts = NULL; | ||
96 | else { | ||
97 | ca->counts = vzalloc(sizeof(*ca->counts) * nr_blocks); | ||
98 | if (!ca->counts) | ||
99 | return -ENOMEM; | ||
100 | } | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static void ca_destroy(struct count_array *ca) | ||
106 | { | ||
107 | vfree(ca->counts); | ||
108 | } | ||
109 | |||
110 | static int ca_load(struct count_array *ca, struct dm_space_map *sm) | ||
111 | { | ||
112 | int r; | ||
113 | uint32_t count; | ||
114 | dm_block_t nr_blocks, i; | ||
115 | |||
116 | r = dm_sm_get_nr_blocks(sm, &nr_blocks); | ||
117 | if (r) | ||
118 | return r; | ||
119 | |||
120 | BUG_ON(ca->nr != nr_blocks); | ||
121 | |||
122 | DMWARN("Loading debug space map from disk. This may take some time"); | ||
123 | for (i = 0; i < nr_blocks; i++) { | ||
124 | r = dm_sm_get_count(sm, i, &count); | ||
125 | if (r) { | ||
126 | DMERR("load failed"); | ||
127 | return r; | ||
128 | } | ||
129 | |||
130 | ca_set_count(ca, i, count); | ||
131 | } | ||
132 | DMWARN("Load complete"); | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static int ca_extend(struct count_array *ca, dm_block_t extra_blocks) | ||
138 | { | ||
139 | dm_block_t nr_blocks = ca->nr + extra_blocks; | ||
140 | uint32_t *counts = vzalloc(sizeof(*counts) * nr_blocks); | ||
141 | if (!counts) | ||
142 | return -ENOMEM; | ||
143 | |||
144 | if (ca->counts) { | ||
145 | memcpy(counts, ca->counts, sizeof(*counts) * ca->nr); | ||
146 | ca_destroy(ca); | ||
147 | } | ||
148 | ca->nr = nr_blocks; | ||
149 | ca->nr_free += extra_blocks; | ||
150 | ca->counts = counts; | ||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static int ca_commit(struct count_array *old, struct count_array *new) | ||
155 | { | ||
156 | if (old->nr != new->nr) { | ||
157 | BUG_ON(old->nr > new->nr); | ||
158 | ca_extend(old, new->nr - old->nr); | ||
159 | } | ||
160 | |||
161 | BUG_ON(old->nr != new->nr); | ||
162 | old->nr_free = new->nr_free; | ||
163 | memcpy(old->counts, new->counts, sizeof(*old->counts) * old->nr); | ||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | /*----------------------------------------------------------------*/ | ||
168 | |||
169 | struct sm_checker { | ||
170 | struct dm_space_map sm; | ||
171 | |||
172 | struct count_array old_counts; | ||
173 | struct count_array counts; | ||
174 | |||
175 | struct dm_space_map *real_sm; | ||
176 | }; | ||
177 | |||
178 | static void sm_checker_destroy(struct dm_space_map *sm) | ||
179 | { | ||
180 | struct sm_checker *smc = container_of(sm, struct sm_checker, sm); | ||
181 | |||
182 | dm_sm_destroy(smc->real_sm); | ||
183 | ca_destroy(&smc->old_counts); | ||
184 | ca_destroy(&smc->counts); | ||
185 | kfree(smc); | ||
186 | } | ||
187 | |||
188 | static int sm_checker_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count) | ||
189 | { | ||
190 | struct sm_checker *smc = container_of(sm, struct sm_checker, sm); | ||
191 | int r = dm_sm_get_nr_blocks(smc->real_sm, count); | ||
192 | if (!r) | ||
193 | BUG_ON(smc->old_counts.nr != *count); | ||
194 | return r; | ||
195 | } | ||
196 | |||
197 | static int sm_checker_get_nr_free(struct dm_space_map *sm, dm_block_t *count) | ||
198 | { | ||
199 | struct sm_checker *smc = container_of(sm, struct sm_checker, sm); | ||
200 | int r = dm_sm_get_nr_free(smc->real_sm, count); | ||
201 | if (!r) { | ||
202 | /* | ||
203 | * Slow, but we know it's correct. | ||
204 | */ | ||
205 | dm_block_t b, n = 0; | ||
206 | for (b = 0; b < smc->old_counts.nr; b++) | ||
207 | if (smc->old_counts.counts[b] == 0 && | ||
208 | smc->counts.counts[b] == 0) | ||
209 | n++; | ||
210 | |||
211 | if (n != *count) | ||
212 | DMERR("free block counts differ, checker %u, sm-disk:%u", | ||
213 | (unsigned) n, (unsigned) *count); | ||
214 | } | ||
215 | return r; | ||
216 | } | ||
217 | |||
218 | static int sm_checker_new_block(struct dm_space_map *sm, dm_block_t *b) | ||
219 | { | ||
220 | struct sm_checker *smc = container_of(sm, struct sm_checker, sm); | ||
221 | int r = dm_sm_new_block(smc->real_sm, b); | ||
222 | |||
223 | if (!r) { | ||
224 | BUG_ON(*b >= smc->old_counts.nr); | ||
225 | BUG_ON(smc->old_counts.counts[*b] != 0); | ||
226 | BUG_ON(*b >= smc->counts.nr); | ||
227 | BUG_ON(smc->counts.counts[*b] != 0); | ||
228 | ca_set_count(&smc->counts, *b, 1); | ||
229 | } | ||
230 | |||
231 | return r; | ||
232 | } | ||
233 | |||
234 | static int sm_checker_inc_block(struct dm_space_map *sm, dm_block_t b) | ||
235 | { | ||
236 | struct sm_checker *smc = container_of(sm, struct sm_checker, sm); | ||
237 | int r = dm_sm_inc_block(smc->real_sm, b); | ||
238 | int r2 = ca_inc_block(&smc->counts, b); | ||
239 | BUG_ON(r != r2); | ||
240 | return r; | ||
241 | } | ||
242 | |||
243 | static int sm_checker_dec_block(struct dm_space_map *sm, dm_block_t b) | ||
244 | { | ||
245 | struct sm_checker *smc = container_of(sm, struct sm_checker, sm); | ||
246 | int r = dm_sm_dec_block(smc->real_sm, b); | ||
247 | int r2 = ca_dec_block(&smc->counts, b); | ||
248 | BUG_ON(r != r2); | ||
249 | return r; | ||
250 | } | ||
251 | |||
252 | static int sm_checker_get_count(struct dm_space_map *sm, dm_block_t b, uint32_t *result) | ||
253 | { | ||
254 | struct sm_checker *smc = container_of(sm, struct sm_checker, sm); | ||
255 | uint32_t result2 = 0; | ||
256 | int r = dm_sm_get_count(smc->real_sm, b, result); | ||
257 | int r2 = ca_get_count(&smc->counts, b, &result2); | ||
258 | |||
259 | BUG_ON(r != r2); | ||
260 | if (!r) | ||
261 | BUG_ON(*result != result2); | ||
262 | return r; | ||
263 | } | ||
264 | |||
265 | static int sm_checker_count_more_than_one(struct dm_space_map *sm, dm_block_t b, int *result) | ||
266 | { | ||
267 | struct sm_checker *smc = container_of(sm, struct sm_checker, sm); | ||
268 | int result2 = 0; | ||
269 | int r = dm_sm_count_is_more_than_one(smc->real_sm, b, result); | ||
270 | int r2 = ca_count_more_than_one(&smc->counts, b, &result2); | ||
271 | |||
272 | BUG_ON(r != r2); | ||
273 | if (!r) | ||
274 | BUG_ON(!(*result) && result2); | ||
275 | return r; | ||
276 | } | ||
277 | |||
278 | static int sm_checker_set_count(struct dm_space_map *sm, dm_block_t b, uint32_t count) | ||
279 | { | ||
280 | struct sm_checker *smc = container_of(sm, struct sm_checker, sm); | ||
281 | uint32_t old_rc; | ||
282 | int r = dm_sm_set_count(smc->real_sm, b, count); | ||
283 | int r2; | ||
284 | |||
285 | BUG_ON(b >= smc->counts.nr); | ||
286 | old_rc = smc->counts.counts[b]; | ||
287 | r2 = ca_set_count(&smc->counts, b, count); | ||
288 | BUG_ON(r != r2); | ||
289 | |||
290 | return r; | ||
291 | } | ||
292 | |||
293 | static int sm_checker_commit(struct dm_space_map *sm) | ||
294 | { | ||
295 | struct sm_checker *smc = container_of(sm, struct sm_checker, sm); | ||
296 | int r; | ||
297 | |||
298 | r = dm_sm_commit(smc->real_sm); | ||
299 | if (r) | ||
300 | return r; | ||
301 | |||
302 | r = ca_commit(&smc->old_counts, &smc->counts); | ||
303 | if (r) | ||
304 | return r; | ||
305 | |||
306 | return 0; | ||
307 | } | ||
308 | |||
309 | static int sm_checker_extend(struct dm_space_map *sm, dm_block_t extra_blocks) | ||
310 | { | ||
311 | struct sm_checker *smc = container_of(sm, struct sm_checker, sm); | ||
312 | int r = dm_sm_extend(smc->real_sm, extra_blocks); | ||
313 | if (r) | ||
314 | return r; | ||
315 | |||
316 | return ca_extend(&smc->counts, extra_blocks); | ||
317 | } | ||
318 | |||
319 | static int sm_checker_root_size(struct dm_space_map *sm, size_t *result) | ||
320 | { | ||
321 | struct sm_checker *smc = container_of(sm, struct sm_checker, sm); | ||
322 | return dm_sm_root_size(smc->real_sm, result); | ||
323 | } | ||
324 | |||
325 | static int sm_checker_copy_root(struct dm_space_map *sm, void *copy_to_here_le, size_t len) | ||
326 | { | ||
327 | struct sm_checker *smc = container_of(sm, struct sm_checker, sm); | ||
328 | return dm_sm_copy_root(smc->real_sm, copy_to_here_le, len); | ||
329 | } | ||
330 | |||
331 | /*----------------------------------------------------------------*/ | ||
332 | |||
333 | static struct dm_space_map ops_ = { | ||
334 | .destroy = sm_checker_destroy, | ||
335 | .get_nr_blocks = sm_checker_get_nr_blocks, | ||
336 | .get_nr_free = sm_checker_get_nr_free, | ||
337 | .inc_block = sm_checker_inc_block, | ||
338 | .dec_block = sm_checker_dec_block, | ||
339 | .new_block = sm_checker_new_block, | ||
340 | .get_count = sm_checker_get_count, | ||
341 | .count_is_more_than_one = sm_checker_count_more_than_one, | ||
342 | .set_count = sm_checker_set_count, | ||
343 | .commit = sm_checker_commit, | ||
344 | .extend = sm_checker_extend, | ||
345 | .root_size = sm_checker_root_size, | ||
346 | .copy_root = sm_checker_copy_root | ||
347 | }; | ||
348 | |||
349 | struct dm_space_map *dm_sm_checker_create(struct dm_space_map *sm) | ||
350 | { | ||
351 | int r; | ||
352 | struct sm_checker *smc; | ||
353 | |||
354 | if (IS_ERR_OR_NULL(sm)) | ||
355 | return ERR_PTR(-EINVAL); | ||
356 | |||
357 | smc = kmalloc(sizeof(*smc), GFP_KERNEL); | ||
358 | if (!smc) | ||
359 | return ERR_PTR(-ENOMEM); | ||
360 | |||
361 | memcpy(&smc->sm, &ops_, sizeof(smc->sm)); | ||
362 | r = ca_create(&smc->old_counts, sm); | ||
363 | if (r) { | ||
364 | kfree(smc); | ||
365 | return ERR_PTR(r); | ||
366 | } | ||
367 | |||
368 | r = ca_create(&smc->counts, sm); | ||
369 | if (r) { | ||
370 | ca_destroy(&smc->old_counts); | ||
371 | kfree(smc); | ||
372 | return ERR_PTR(r); | ||
373 | } | ||
374 | |||
375 | smc->real_sm = sm; | ||
376 | |||
377 | r = ca_load(&smc->counts, sm); | ||
378 | if (r) { | ||
379 | ca_destroy(&smc->counts); | ||
380 | ca_destroy(&smc->old_counts); | ||
381 | kfree(smc); | ||
382 | return ERR_PTR(r); | ||
383 | } | ||
384 | |||
385 | r = ca_commit(&smc->old_counts, &smc->counts); | ||
386 | if (r) { | ||
387 | ca_destroy(&smc->counts); | ||
388 | ca_destroy(&smc->old_counts); | ||
389 | kfree(smc); | ||
390 | return ERR_PTR(r); | ||
391 | } | ||
392 | |||
393 | return &smc->sm; | ||
394 | } | ||
395 | EXPORT_SYMBOL_GPL(dm_sm_checker_create); | ||
396 | |||
397 | struct dm_space_map *dm_sm_checker_create_fresh(struct dm_space_map *sm) | ||
398 | { | ||
399 | int r; | ||
400 | struct sm_checker *smc; | ||
401 | |||
402 | if (IS_ERR_OR_NULL(sm)) | ||
403 | return ERR_PTR(-EINVAL); | ||
404 | |||
405 | smc = kmalloc(sizeof(*smc), GFP_KERNEL); | ||
406 | if (!smc) | ||
407 | return ERR_PTR(-ENOMEM); | ||
408 | |||
409 | memcpy(&smc->sm, &ops_, sizeof(smc->sm)); | ||
410 | r = ca_create(&smc->old_counts, sm); | ||
411 | if (r) { | ||
412 | kfree(smc); | ||
413 | return ERR_PTR(r); | ||
414 | } | ||
415 | |||
416 | r = ca_create(&smc->counts, sm); | ||
417 | if (r) { | ||
418 | ca_destroy(&smc->old_counts); | ||
419 | kfree(smc); | ||
420 | return ERR_PTR(r); | ||
421 | } | ||
422 | |||
423 | smc->real_sm = sm; | ||
424 | return &smc->sm; | ||
425 | } | ||
426 | EXPORT_SYMBOL_GPL(dm_sm_checker_create_fresh); | ||
427 | |||
428 | /*----------------------------------------------------------------*/ | ||
429 | |||
430 | #else | ||
431 | |||
432 | struct dm_space_map *dm_sm_checker_create(struct dm_space_map *sm) | ||
433 | { | ||
434 | return sm; | ||
435 | } | ||
436 | EXPORT_SYMBOL_GPL(dm_sm_checker_create); | ||
437 | |||
438 | struct dm_space_map *dm_sm_checker_create_fresh(struct dm_space_map *sm) | ||
439 | { | ||
440 | return sm; | ||
441 | } | ||
442 | EXPORT_SYMBOL_GPL(dm_sm_checker_create_fresh); | ||
443 | |||
444 | /*----------------------------------------------------------------*/ | ||
445 | |||
446 | #endif | ||
diff --git a/drivers/md/persistent-data/dm-space-map-checker.h b/drivers/md/persistent-data/dm-space-map-checker.h deleted file mode 100644 index 444dccf6688c..000000000000 --- a/drivers/md/persistent-data/dm-space-map-checker.h +++ /dev/null | |||
@@ -1,26 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Red Hat, Inc. | ||
3 | * | ||
4 | * This file is released under the GPL. | ||
5 | */ | ||
6 | |||
7 | #ifndef SNAPSHOTS_SPACE_MAP_CHECKER_H | ||
8 | #define SNAPSHOTS_SPACE_MAP_CHECKER_H | ||
9 | |||
10 | #include "dm-space-map.h" | ||
11 | |||
12 | /*----------------------------------------------------------------*/ | ||
13 | |||
14 | /* | ||
15 | * This space map wraps a real on-disk space map, and verifies all of its | ||
16 | * operations. It uses a lot of memory, so only use if you have a specific | ||
17 | * problem that you're debugging. | ||
18 | * | ||
19 | * Ownership of @sm passes. | ||
20 | */ | ||
21 | struct dm_space_map *dm_sm_checker_create(struct dm_space_map *sm); | ||
22 | struct dm_space_map *dm_sm_checker_create_fresh(struct dm_space_map *sm); | ||
23 | |||
24 | /*----------------------------------------------------------------*/ | ||
25 | |||
26 | #endif | ||
diff --git a/drivers/md/persistent-data/dm-space-map-disk.c b/drivers/md/persistent-data/dm-space-map-disk.c index 3d0ed5332883..f6d29e614ab7 100644 --- a/drivers/md/persistent-data/dm-space-map-disk.c +++ b/drivers/md/persistent-data/dm-space-map-disk.c | |||
@@ -4,7 +4,6 @@ | |||
4 | * This file is released under the GPL. | 4 | * This file is released under the GPL. |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include "dm-space-map-checker.h" | ||
8 | #include "dm-space-map-common.h" | 7 | #include "dm-space-map-common.h" |
9 | #include "dm-space-map-disk.h" | 8 | #include "dm-space-map-disk.h" |
10 | #include "dm-space-map.h" | 9 | #include "dm-space-map.h" |
@@ -252,9 +251,8 @@ static struct dm_space_map ops = { | |||
252 | .copy_root = sm_disk_copy_root | 251 | .copy_root = sm_disk_copy_root |
253 | }; | 252 | }; |
254 | 253 | ||
255 | static struct dm_space_map *dm_sm_disk_create_real( | 254 | struct dm_space_map *dm_sm_disk_create(struct dm_transaction_manager *tm, |
256 | struct dm_transaction_manager *tm, | 255 | dm_block_t nr_blocks) |
257 | dm_block_t nr_blocks) | ||
258 | { | 256 | { |
259 | int r; | 257 | int r; |
260 | struct sm_disk *smd; | 258 | struct sm_disk *smd; |
@@ -285,27 +283,10 @@ bad: | |||
285 | kfree(smd); | 283 | kfree(smd); |
286 | return ERR_PTR(r); | 284 | return ERR_PTR(r); |
287 | } | 285 | } |
288 | |||
289 | struct dm_space_map *dm_sm_disk_create(struct dm_transaction_manager *tm, | ||
290 | dm_block_t nr_blocks) | ||
291 | { | ||
292 | struct dm_space_map *sm = dm_sm_disk_create_real(tm, nr_blocks); | ||
293 | struct dm_space_map *smc; | ||
294 | |||
295 | if (IS_ERR_OR_NULL(sm)) | ||
296 | return sm; | ||
297 | |||
298 | smc = dm_sm_checker_create_fresh(sm); | ||
299 | if (IS_ERR(smc)) | ||
300 | dm_sm_destroy(sm); | ||
301 | |||
302 | return smc; | ||
303 | } | ||
304 | EXPORT_SYMBOL_GPL(dm_sm_disk_create); | 286 | EXPORT_SYMBOL_GPL(dm_sm_disk_create); |
305 | 287 | ||
306 | static struct dm_space_map *dm_sm_disk_open_real( | 288 | struct dm_space_map *dm_sm_disk_open(struct dm_transaction_manager *tm, |
307 | struct dm_transaction_manager *tm, | 289 | void *root_le, size_t len) |
308 | void *root_le, size_t len) | ||
309 | { | 290 | { |
310 | int r; | 291 | int r; |
311 | struct sm_disk *smd; | 292 | struct sm_disk *smd; |
@@ -332,13 +313,6 @@ bad: | |||
332 | kfree(smd); | 313 | kfree(smd); |
333 | return ERR_PTR(r); | 314 | return ERR_PTR(r); |
334 | } | 315 | } |
335 | |||
336 | struct dm_space_map *dm_sm_disk_open(struct dm_transaction_manager *tm, | ||
337 | void *root_le, size_t len) | ||
338 | { | ||
339 | return dm_sm_checker_create( | ||
340 | dm_sm_disk_open_real(tm, root_le, len)); | ||
341 | } | ||
342 | EXPORT_SYMBOL_GPL(dm_sm_disk_open); | 316 | EXPORT_SYMBOL_GPL(dm_sm_disk_open); |
343 | 317 | ||
344 | /*----------------------------------------------------------------*/ | 318 | /*----------------------------------------------------------------*/ |
diff --git a/drivers/md/persistent-data/dm-transaction-manager.c b/drivers/md/persistent-data/dm-transaction-manager.c index e5604b32d91f..86c3705052a4 100644 --- a/drivers/md/persistent-data/dm-transaction-manager.c +++ b/drivers/md/persistent-data/dm-transaction-manager.c | |||
@@ -5,7 +5,6 @@ | |||
5 | */ | 5 | */ |
6 | #include "dm-transaction-manager.h" | 6 | #include "dm-transaction-manager.h" |
7 | #include "dm-space-map.h" | 7 | #include "dm-space-map.h" |
8 | #include "dm-space-map-checker.h" | ||
9 | #include "dm-space-map-disk.h" | 8 | #include "dm-space-map-disk.h" |
10 | #include "dm-space-map-metadata.h" | 9 | #include "dm-space-map-metadata.h" |
11 | #include "dm-persistent-data-internal.h" | 10 | #include "dm-persistent-data-internal.h" |
@@ -319,15 +318,14 @@ static int dm_tm_create_internal(struct dm_block_manager *bm, | |||
319 | int create) | 318 | int create) |
320 | { | 319 | { |
321 | int r; | 320 | int r; |
322 | struct dm_space_map *inner; | ||
323 | 321 | ||
324 | inner = dm_sm_metadata_init(); | 322 | *sm = dm_sm_metadata_init(); |
325 | if (IS_ERR(inner)) | 323 | if (IS_ERR(*sm)) |
326 | return PTR_ERR(inner); | 324 | return PTR_ERR(*sm); |
327 | 325 | ||
328 | *tm = dm_tm_create(bm, inner); | 326 | *tm = dm_tm_create(bm, *sm); |
329 | if (IS_ERR(*tm)) { | 327 | if (IS_ERR(*tm)) { |
330 | dm_sm_destroy(inner); | 328 | dm_sm_destroy(*sm); |
331 | return PTR_ERR(*tm); | 329 | return PTR_ERR(*tm); |
332 | } | 330 | } |
333 | 331 | ||
@@ -339,19 +337,13 @@ static int dm_tm_create_internal(struct dm_block_manager *bm, | |||
339 | goto bad1; | 337 | goto bad1; |
340 | } | 338 | } |
341 | 339 | ||
342 | r = dm_sm_metadata_create(inner, *tm, dm_bm_nr_blocks(bm), | 340 | r = dm_sm_metadata_create(*sm, *tm, dm_bm_nr_blocks(bm), |
343 | sb_location); | 341 | sb_location); |
344 | if (r) { | 342 | if (r) { |
345 | DMERR("couldn't create metadata space map"); | 343 | DMERR("couldn't create metadata space map"); |
346 | goto bad2; | 344 | goto bad2; |
347 | } | 345 | } |
348 | 346 | ||
349 | *sm = dm_sm_checker_create(inner); | ||
350 | if (IS_ERR(*sm)) { | ||
351 | r = PTR_ERR(*sm); | ||
352 | goto bad2; | ||
353 | } | ||
354 | |||
355 | } else { | 347 | } else { |
356 | r = dm_bm_write_lock(dm_tm_get_bm(*tm), sb_location, | 348 | r = dm_bm_write_lock(dm_tm_get_bm(*tm), sb_location, |
357 | sb_validator, sblock); | 349 | sb_validator, sblock); |
@@ -360,19 +352,13 @@ static int dm_tm_create_internal(struct dm_block_manager *bm, | |||
360 | goto bad1; | 352 | goto bad1; |
361 | } | 353 | } |
362 | 354 | ||
363 | r = dm_sm_metadata_open(inner, *tm, | 355 | r = dm_sm_metadata_open(*sm, *tm, |
364 | dm_block_data(*sblock) + root_offset, | 356 | dm_block_data(*sblock) + root_offset, |
365 | root_max_len); | 357 | root_max_len); |
366 | if (r) { | 358 | if (r) { |
367 | DMERR("couldn't open metadata space map"); | 359 | DMERR("couldn't open metadata space map"); |
368 | goto bad2; | 360 | goto bad2; |
369 | } | 361 | } |
370 | |||
371 | *sm = dm_sm_checker_create(inner); | ||
372 | if (IS_ERR(*sm)) { | ||
373 | r = PTR_ERR(*sm); | ||
374 | goto bad2; | ||
375 | } | ||
376 | } | 362 | } |
377 | 363 | ||
378 | return 0; | 364 | return 0; |
@@ -381,7 +367,6 @@ bad2: | |||
381 | dm_tm_unlock(*tm, *sblock); | 367 | dm_tm_unlock(*tm, *sblock); |
382 | bad1: | 368 | bad1: |
383 | dm_tm_destroy(*tm); | 369 | dm_tm_destroy(*tm); |
384 | dm_sm_destroy(inner); | ||
385 | return r; | 370 | return r; |
386 | } | 371 | } |
387 | 372 | ||