.. | .. |
---|
6 | 6 | #include <linux/types.h> |
---|
7 | 7 | #include "btrfs-tests.h" |
---|
8 | 8 | #include "../ctree.h" |
---|
| 9 | +#include "../volumes.h" |
---|
| 10 | +#include "../disk-io.h" |
---|
| 11 | +#include "../block-group.h" |
---|
9 | 12 | |
---|
10 | 13 | static void free_extent_map_tree(struct extent_map_tree *em_tree) |
---|
11 | 14 | { |
---|
12 | 15 | struct extent_map *em; |
---|
13 | 16 | struct rb_node *node; |
---|
14 | 17 | |
---|
15 | | - while (!RB_EMPTY_ROOT(&em_tree->map)) { |
---|
16 | | - node = rb_first(&em_tree->map); |
---|
| 18 | + while (!RB_EMPTY_ROOT(&em_tree->map.rb_root)) { |
---|
| 19 | + node = rb_first_cached(&em_tree->map); |
---|
17 | 20 | em = rb_entry(node, struct extent_map, rb_node); |
---|
18 | 21 | remove_extent_mapping(em_tree, em); |
---|
19 | 22 | |
---|
.. | .. |
---|
47 | 50 | * ->add_extent_mapping(0, 16K) |
---|
48 | 51 | * -> #handle -EEXIST |
---|
49 | 52 | */ |
---|
50 | | -static void test_case_1(struct btrfs_fs_info *fs_info, |
---|
| 53 | +static int test_case_1(struct btrfs_fs_info *fs_info, |
---|
51 | 54 | struct extent_map_tree *em_tree) |
---|
52 | 55 | { |
---|
53 | 56 | struct extent_map *em; |
---|
.. | .. |
---|
56 | 59 | int ret; |
---|
57 | 60 | |
---|
58 | 61 | em = alloc_extent_map(); |
---|
59 | | - if (!em) |
---|
60 | | - /* Skip the test on error. */ |
---|
61 | | - return; |
---|
| 62 | + if (!em) { |
---|
| 63 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
---|
| 64 | + return -ENOMEM; |
---|
| 65 | + } |
---|
62 | 66 | |
---|
63 | 67 | /* Add [0, 16K) */ |
---|
64 | 68 | em->start = 0; |
---|
65 | 69 | em->len = SZ_16K; |
---|
66 | 70 | em->block_start = 0; |
---|
67 | 71 | em->block_len = SZ_16K; |
---|
| 72 | + write_lock(&em_tree->lock); |
---|
68 | 73 | ret = add_extent_mapping(em_tree, em, 0); |
---|
69 | | - ASSERT(ret == 0); |
---|
| 74 | + write_unlock(&em_tree->lock); |
---|
| 75 | + if (ret < 0) { |
---|
| 76 | + test_err("cannot add extent range [0, 16K)"); |
---|
| 77 | + goto out; |
---|
| 78 | + } |
---|
70 | 79 | free_extent_map(em); |
---|
71 | 80 | |
---|
72 | 81 | /* Add [16K, 20K) following [0, 16K) */ |
---|
73 | 82 | em = alloc_extent_map(); |
---|
74 | | - if (!em) |
---|
| 83 | + if (!em) { |
---|
| 84 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
---|
| 85 | + ret = -ENOMEM; |
---|
75 | 86 | goto out; |
---|
| 87 | + } |
---|
76 | 88 | |
---|
77 | 89 | em->start = SZ_16K; |
---|
78 | 90 | em->len = SZ_4K; |
---|
79 | 91 | em->block_start = SZ_32K; /* avoid merging */ |
---|
80 | 92 | em->block_len = SZ_4K; |
---|
| 93 | + write_lock(&em_tree->lock); |
---|
81 | 94 | ret = add_extent_mapping(em_tree, em, 0); |
---|
82 | | - ASSERT(ret == 0); |
---|
| 95 | + write_unlock(&em_tree->lock); |
---|
| 96 | + if (ret < 0) { |
---|
| 97 | + test_err("cannot add extent range [16K, 20K)"); |
---|
| 98 | + goto out; |
---|
| 99 | + } |
---|
83 | 100 | free_extent_map(em); |
---|
84 | 101 | |
---|
85 | 102 | em = alloc_extent_map(); |
---|
86 | | - if (!em) |
---|
| 103 | + if (!em) { |
---|
| 104 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
---|
| 105 | + ret = -ENOMEM; |
---|
87 | 106 | goto out; |
---|
| 107 | + } |
---|
88 | 108 | |
---|
89 | 109 | /* Add [0, 8K), should return [0, 16K) instead. */ |
---|
90 | 110 | em->start = start; |
---|
91 | 111 | em->len = len; |
---|
92 | 112 | em->block_start = start; |
---|
93 | 113 | em->block_len = len; |
---|
| 114 | + write_lock(&em_tree->lock); |
---|
94 | 115 | ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, em->start, em->len); |
---|
95 | | - if (ret) |
---|
| 116 | + write_unlock(&em_tree->lock); |
---|
| 117 | + if (ret) { |
---|
96 | 118 | test_err("case1 [%llu %llu]: ret %d", start, start + len, ret); |
---|
| 119 | + goto out; |
---|
| 120 | + } |
---|
97 | 121 | if (em && |
---|
98 | 122 | (em->start != 0 || extent_map_end(em) != SZ_16K || |
---|
99 | | - em->block_start != 0 || em->block_len != SZ_16K)) |
---|
| 123 | + em->block_start != 0 || em->block_len != SZ_16K)) { |
---|
100 | 124 | test_err( |
---|
101 | 125 | "case1 [%llu %llu]: ret %d return a wrong em (start %llu len %llu block_start %llu block_len %llu", |
---|
102 | 126 | start, start + len, ret, em->start, em->len, |
---|
103 | 127 | em->block_start, em->block_len); |
---|
| 128 | + ret = -EINVAL; |
---|
| 129 | + } |
---|
104 | 130 | free_extent_map(em); |
---|
105 | 131 | out: |
---|
106 | | - /* free memory */ |
---|
107 | 132 | free_extent_map_tree(em_tree); |
---|
| 133 | + |
---|
| 134 | + return ret; |
---|
108 | 135 | } |
---|
109 | 136 | |
---|
110 | 137 | /* |
---|
.. | .. |
---|
113 | 140 | * Reading the inline ending up with EEXIST, ie. read an inline |
---|
114 | 141 | * extent and discard page cache and read it again. |
---|
115 | 142 | */ |
---|
116 | | -static void test_case_2(struct btrfs_fs_info *fs_info, |
---|
| 143 | +static int test_case_2(struct btrfs_fs_info *fs_info, |
---|
117 | 144 | struct extent_map_tree *em_tree) |
---|
118 | 145 | { |
---|
119 | 146 | struct extent_map *em; |
---|
120 | 147 | int ret; |
---|
121 | 148 | |
---|
122 | 149 | em = alloc_extent_map(); |
---|
123 | | - if (!em) |
---|
124 | | - /* Skip the test on error. */ |
---|
125 | | - return; |
---|
| 150 | + if (!em) { |
---|
| 151 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
---|
| 152 | + return -ENOMEM; |
---|
| 153 | + } |
---|
126 | 154 | |
---|
127 | 155 | /* Add [0, 1K) */ |
---|
128 | 156 | em->start = 0; |
---|
129 | 157 | em->len = SZ_1K; |
---|
130 | 158 | em->block_start = EXTENT_MAP_INLINE; |
---|
131 | 159 | em->block_len = (u64)-1; |
---|
| 160 | + write_lock(&em_tree->lock); |
---|
132 | 161 | ret = add_extent_mapping(em_tree, em, 0); |
---|
133 | | - ASSERT(ret == 0); |
---|
| 162 | + write_unlock(&em_tree->lock); |
---|
| 163 | + if (ret < 0) { |
---|
| 164 | + test_err("cannot add extent range [0, 1K)"); |
---|
| 165 | + goto out; |
---|
| 166 | + } |
---|
134 | 167 | free_extent_map(em); |
---|
135 | 168 | |
---|
136 | | - /* Add [4K, 4K) following [0, 1K) */ |
---|
| 169 | + /* Add [4K, 8K) following [0, 1K) */ |
---|
137 | 170 | em = alloc_extent_map(); |
---|
138 | | - if (!em) |
---|
| 171 | + if (!em) { |
---|
| 172 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
---|
| 173 | + ret = -ENOMEM; |
---|
139 | 174 | goto out; |
---|
| 175 | + } |
---|
140 | 176 | |
---|
141 | 177 | em->start = SZ_4K; |
---|
142 | 178 | em->len = SZ_4K; |
---|
143 | 179 | em->block_start = SZ_4K; |
---|
144 | 180 | em->block_len = SZ_4K; |
---|
| 181 | + write_lock(&em_tree->lock); |
---|
145 | 182 | ret = add_extent_mapping(em_tree, em, 0); |
---|
146 | | - ASSERT(ret == 0); |
---|
| 183 | + write_unlock(&em_tree->lock); |
---|
| 184 | + if (ret < 0) { |
---|
| 185 | + test_err("cannot add extent range [4K, 8K)"); |
---|
| 186 | + goto out; |
---|
| 187 | + } |
---|
147 | 188 | free_extent_map(em); |
---|
148 | 189 | |
---|
149 | 190 | em = alloc_extent_map(); |
---|
150 | | - if (!em) |
---|
| 191 | + if (!em) { |
---|
| 192 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
---|
| 193 | + ret = -ENOMEM; |
---|
151 | 194 | goto out; |
---|
| 195 | + } |
---|
152 | 196 | |
---|
153 | 197 | /* Add [0, 1K) */ |
---|
154 | 198 | em->start = 0; |
---|
155 | 199 | em->len = SZ_1K; |
---|
156 | 200 | em->block_start = EXTENT_MAP_INLINE; |
---|
157 | 201 | em->block_len = (u64)-1; |
---|
| 202 | + write_lock(&em_tree->lock); |
---|
158 | 203 | ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, em->start, em->len); |
---|
159 | | - if (ret) |
---|
| 204 | + write_unlock(&em_tree->lock); |
---|
| 205 | + if (ret) { |
---|
160 | 206 | test_err("case2 [0 1K]: ret %d", ret); |
---|
| 207 | + goto out; |
---|
| 208 | + } |
---|
161 | 209 | if (em && |
---|
162 | 210 | (em->start != 0 || extent_map_end(em) != SZ_1K || |
---|
163 | | - em->block_start != EXTENT_MAP_INLINE || em->block_len != (u64)-1)) |
---|
| 211 | + em->block_start != EXTENT_MAP_INLINE || em->block_len != (u64)-1)) { |
---|
164 | 212 | test_err( |
---|
165 | 213 | "case2 [0 1K]: ret %d return a wrong em (start %llu len %llu block_start %llu block_len %llu", |
---|
166 | 214 | ret, em->start, em->len, em->block_start, |
---|
167 | 215 | em->block_len); |
---|
| 216 | + ret = -EINVAL; |
---|
| 217 | + } |
---|
168 | 218 | free_extent_map(em); |
---|
169 | 219 | out: |
---|
170 | | - /* free memory */ |
---|
171 | 220 | free_extent_map_tree(em_tree); |
---|
| 221 | + |
---|
| 222 | + return ret; |
---|
172 | 223 | } |
---|
173 | 224 | |
---|
174 | | -static void __test_case_3(struct btrfs_fs_info *fs_info, |
---|
| 225 | +static int __test_case_3(struct btrfs_fs_info *fs_info, |
---|
175 | 226 | struct extent_map_tree *em_tree, u64 start) |
---|
176 | 227 | { |
---|
177 | 228 | struct extent_map *em; |
---|
.. | .. |
---|
179 | 230 | int ret; |
---|
180 | 231 | |
---|
181 | 232 | em = alloc_extent_map(); |
---|
182 | | - if (!em) |
---|
183 | | - /* Skip this test on error. */ |
---|
184 | | - return; |
---|
| 233 | + if (!em) { |
---|
| 234 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
---|
| 235 | + return -ENOMEM; |
---|
| 236 | + } |
---|
185 | 237 | |
---|
186 | 238 | /* Add [4K, 8K) */ |
---|
187 | 239 | em->start = SZ_4K; |
---|
188 | 240 | em->len = SZ_4K; |
---|
189 | 241 | em->block_start = SZ_4K; |
---|
190 | 242 | em->block_len = SZ_4K; |
---|
| 243 | + write_lock(&em_tree->lock); |
---|
191 | 244 | ret = add_extent_mapping(em_tree, em, 0); |
---|
192 | | - ASSERT(ret == 0); |
---|
| 245 | + write_unlock(&em_tree->lock); |
---|
| 246 | + if (ret < 0) { |
---|
| 247 | + test_err("cannot add extent range [4K, 8K)"); |
---|
| 248 | + goto out; |
---|
| 249 | + } |
---|
193 | 250 | free_extent_map(em); |
---|
194 | 251 | |
---|
195 | 252 | em = alloc_extent_map(); |
---|
196 | | - if (!em) |
---|
| 253 | + if (!em) { |
---|
| 254 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
---|
| 255 | + ret = -ENOMEM; |
---|
197 | 256 | goto out; |
---|
| 257 | + } |
---|
198 | 258 | |
---|
199 | 259 | /* Add [0, 16K) */ |
---|
200 | 260 | em->start = 0; |
---|
201 | 261 | em->len = SZ_16K; |
---|
202 | 262 | em->block_start = 0; |
---|
203 | 263 | em->block_len = SZ_16K; |
---|
| 264 | + write_lock(&em_tree->lock); |
---|
204 | 265 | ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, start, len); |
---|
205 | | - if (ret) |
---|
| 266 | + write_unlock(&em_tree->lock); |
---|
| 267 | + if (ret) { |
---|
206 | 268 | test_err("case3 [0x%llx 0x%llx): ret %d", |
---|
207 | 269 | start, start + len, ret); |
---|
| 270 | + goto out; |
---|
| 271 | + } |
---|
208 | 272 | /* |
---|
209 | 273 | * Since bytes within em are contiguous, em->block_start is identical to |
---|
210 | 274 | * em->start. |
---|
211 | 275 | */ |
---|
212 | 276 | if (em && |
---|
213 | 277 | (start < em->start || start + len > extent_map_end(em) || |
---|
214 | | - em->start != em->block_start || em->len != em->block_len)) |
---|
| 278 | + em->start != em->block_start || em->len != em->block_len)) { |
---|
215 | 279 | test_err( |
---|
216 | 280 | "case3 [0x%llx 0x%llx): ret %d em (start 0x%llx len 0x%llx block_start 0x%llx block_len 0x%llx)", |
---|
217 | 281 | start, start + len, ret, em->start, em->len, |
---|
218 | 282 | em->block_start, em->block_len); |
---|
| 283 | + ret = -EINVAL; |
---|
| 284 | + } |
---|
219 | 285 | free_extent_map(em); |
---|
220 | 286 | out: |
---|
221 | | - /* free memory */ |
---|
222 | 287 | free_extent_map_tree(em_tree); |
---|
| 288 | + |
---|
| 289 | + return ret; |
---|
223 | 290 | } |
---|
224 | 291 | |
---|
225 | 292 | /* |
---|
.. | .. |
---|
238 | 305 | * -> add_extent_mapping() |
---|
239 | 306 | * -> add_extent_mapping() |
---|
240 | 307 | */ |
---|
241 | | -static void test_case_3(struct btrfs_fs_info *fs_info, |
---|
| 308 | +static int test_case_3(struct btrfs_fs_info *fs_info, |
---|
242 | 309 | struct extent_map_tree *em_tree) |
---|
243 | 310 | { |
---|
244 | | - __test_case_3(fs_info, em_tree, 0); |
---|
245 | | - __test_case_3(fs_info, em_tree, SZ_8K); |
---|
246 | | - __test_case_3(fs_info, em_tree, (12 * 1024ULL)); |
---|
| 311 | + int ret; |
---|
| 312 | + |
---|
| 313 | + ret = __test_case_3(fs_info, em_tree, 0); |
---|
| 314 | + if (ret) |
---|
| 315 | + return ret; |
---|
| 316 | + ret = __test_case_3(fs_info, em_tree, SZ_8K); |
---|
| 317 | + if (ret) |
---|
| 318 | + return ret; |
---|
| 319 | + ret = __test_case_3(fs_info, em_tree, (12 * SZ_1K)); |
---|
| 320 | + |
---|
| 321 | + return ret; |
---|
247 | 322 | } |
---|
248 | 323 | |
---|
249 | | -static void __test_case_4(struct btrfs_fs_info *fs_info, |
---|
| 324 | +static int __test_case_4(struct btrfs_fs_info *fs_info, |
---|
250 | 325 | struct extent_map_tree *em_tree, u64 start) |
---|
251 | 326 | { |
---|
252 | 327 | struct extent_map *em; |
---|
.. | .. |
---|
254 | 329 | int ret; |
---|
255 | 330 | |
---|
256 | 331 | em = alloc_extent_map(); |
---|
257 | | - if (!em) |
---|
258 | | - /* Skip this test on error. */ |
---|
259 | | - return; |
---|
| 332 | + if (!em) { |
---|
| 333 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
---|
| 334 | + return -ENOMEM; |
---|
| 335 | + } |
---|
260 | 336 | |
---|
261 | 337 | /* Add [0K, 8K) */ |
---|
262 | 338 | em->start = 0; |
---|
263 | 339 | em->len = SZ_8K; |
---|
264 | 340 | em->block_start = 0; |
---|
265 | 341 | em->block_len = SZ_8K; |
---|
| 342 | + write_lock(&em_tree->lock); |
---|
266 | 343 | ret = add_extent_mapping(em_tree, em, 0); |
---|
267 | | - ASSERT(ret == 0); |
---|
| 344 | + write_unlock(&em_tree->lock); |
---|
| 345 | + if (ret < 0) { |
---|
| 346 | + test_err("cannot add extent range [0, 8K)"); |
---|
| 347 | + goto out; |
---|
| 348 | + } |
---|
268 | 349 | free_extent_map(em); |
---|
269 | 350 | |
---|
270 | 351 | em = alloc_extent_map(); |
---|
271 | | - if (!em) |
---|
| 352 | + if (!em) { |
---|
| 353 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
---|
| 354 | + ret = -ENOMEM; |
---|
272 | 355 | goto out; |
---|
| 356 | + } |
---|
273 | 357 | |
---|
274 | | - /* Add [8K, 24K) */ |
---|
| 358 | + /* Add [8K, 32K) */ |
---|
275 | 359 | em->start = SZ_8K; |
---|
276 | | - em->len = 24 * 1024ULL; |
---|
| 360 | + em->len = 24 * SZ_1K; |
---|
277 | 361 | em->block_start = SZ_16K; /* avoid merging */ |
---|
278 | | - em->block_len = 24 * 1024ULL; |
---|
| 362 | + em->block_len = 24 * SZ_1K; |
---|
| 363 | + write_lock(&em_tree->lock); |
---|
279 | 364 | ret = add_extent_mapping(em_tree, em, 0); |
---|
280 | | - ASSERT(ret == 0); |
---|
| 365 | + write_unlock(&em_tree->lock); |
---|
| 366 | + if (ret < 0) { |
---|
| 367 | + test_err("cannot add extent range [8K, 32K)"); |
---|
| 368 | + goto out; |
---|
| 369 | + } |
---|
281 | 370 | free_extent_map(em); |
---|
282 | 371 | |
---|
283 | 372 | em = alloc_extent_map(); |
---|
284 | | - if (!em) |
---|
| 373 | + if (!em) { |
---|
| 374 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
---|
| 375 | + ret = -ENOMEM; |
---|
285 | 376 | goto out; |
---|
| 377 | + } |
---|
286 | 378 | /* Add [0K, 32K) */ |
---|
287 | 379 | em->start = 0; |
---|
288 | 380 | em->len = SZ_32K; |
---|
289 | 381 | em->block_start = 0; |
---|
290 | 382 | em->block_len = SZ_32K; |
---|
| 383 | + write_lock(&em_tree->lock); |
---|
291 | 384 | ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, start, len); |
---|
292 | | - if (ret) |
---|
| 385 | + write_unlock(&em_tree->lock); |
---|
| 386 | + if (ret) { |
---|
293 | 387 | test_err("case4 [0x%llx 0x%llx): ret %d", |
---|
294 | 388 | start, len, ret); |
---|
295 | | - if (em && |
---|
296 | | - (start < em->start || start + len > extent_map_end(em))) |
---|
| 389 | + goto out; |
---|
| 390 | + } |
---|
| 391 | + if (em && (start < em->start || start + len > extent_map_end(em))) { |
---|
297 | 392 | test_err( |
---|
298 | 393 | "case4 [0x%llx 0x%llx): ret %d, added wrong em (start 0x%llx len 0x%llx block_start 0x%llx block_len 0x%llx)", |
---|
299 | 394 | start, len, ret, em->start, em->len, em->block_start, |
---|
300 | 395 | em->block_len); |
---|
| 396 | + ret = -EINVAL; |
---|
| 397 | + } |
---|
301 | 398 | free_extent_map(em); |
---|
302 | 399 | out: |
---|
303 | | - /* free memory */ |
---|
304 | 400 | free_extent_map_tree(em_tree); |
---|
| 401 | + |
---|
| 402 | + return ret; |
---|
305 | 403 | } |
---|
306 | 404 | |
---|
307 | 405 | /* |
---|
.. | .. |
---|
329 | 427 | * # handle -EEXIST when adding |
---|
330 | 428 | * # [0, 32K) |
---|
331 | 429 | */ |
---|
332 | | -static void test_case_4(struct btrfs_fs_info *fs_info, |
---|
| 430 | +static int test_case_4(struct btrfs_fs_info *fs_info, |
---|
333 | 431 | struct extent_map_tree *em_tree) |
---|
334 | 432 | { |
---|
335 | | - __test_case_4(fs_info, em_tree, 0); |
---|
336 | | - __test_case_4(fs_info, em_tree, SZ_4K); |
---|
| 433 | + int ret; |
---|
| 434 | + |
---|
| 435 | + ret = __test_case_4(fs_info, em_tree, 0); |
---|
| 436 | + if (ret) |
---|
| 437 | + return ret; |
---|
| 438 | + ret = __test_case_4(fs_info, em_tree, SZ_4K); |
---|
| 439 | + |
---|
| 440 | + return ret; |
---|
| 441 | +} |
---|
| 442 | + |
---|
| 443 | +struct rmap_test_vector { |
---|
| 444 | + u64 raid_type; |
---|
| 445 | + u64 physical_start; |
---|
| 446 | + u64 data_stripe_size; |
---|
| 447 | + u64 num_data_stripes; |
---|
| 448 | + u64 num_stripes; |
---|
| 449 | + /* Assume we won't have more than 5 physical stripes */ |
---|
| 450 | + u64 data_stripe_phys_start[5]; |
---|
| 451 | + bool expected_mapped_addr; |
---|
| 452 | + /* Physical to logical addresses */ |
---|
| 453 | + u64 mapped_logical[5]; |
---|
| 454 | +}; |
---|
| 455 | + |
---|
| 456 | +static int test_rmap_block(struct btrfs_fs_info *fs_info, |
---|
| 457 | + struct rmap_test_vector *test) |
---|
| 458 | +{ |
---|
| 459 | + struct extent_map *em; |
---|
| 460 | + struct map_lookup *map = NULL; |
---|
| 461 | + u64 *logical = NULL; |
---|
| 462 | + int i, out_ndaddrs, out_stripe_len; |
---|
| 463 | + int ret; |
---|
| 464 | + |
---|
| 465 | + em = alloc_extent_map(); |
---|
| 466 | + if (!em) { |
---|
| 467 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
---|
| 468 | + return -ENOMEM; |
---|
| 469 | + } |
---|
| 470 | + |
---|
| 471 | + map = kmalloc(map_lookup_size(test->num_stripes), GFP_KERNEL); |
---|
| 472 | + if (!map) { |
---|
| 473 | + kfree(em); |
---|
| 474 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
---|
| 475 | + return -ENOMEM; |
---|
| 476 | + } |
---|
| 477 | + |
---|
| 478 | + set_bit(EXTENT_FLAG_FS_MAPPING, &em->flags); |
---|
| 479 | + /* Start at 4GiB logical address */ |
---|
| 480 | + em->start = SZ_4G; |
---|
| 481 | + em->len = test->data_stripe_size * test->num_data_stripes; |
---|
| 482 | + em->block_len = em->len; |
---|
| 483 | + em->orig_block_len = test->data_stripe_size; |
---|
| 484 | + em->map_lookup = map; |
---|
| 485 | + |
---|
| 486 | + map->num_stripes = test->num_stripes; |
---|
| 487 | + map->stripe_len = BTRFS_STRIPE_LEN; |
---|
| 488 | + map->type = test->raid_type; |
---|
| 489 | + |
---|
| 490 | + for (i = 0; i < map->num_stripes; i++) { |
---|
| 491 | + struct btrfs_device *dev = btrfs_alloc_dummy_device(fs_info); |
---|
| 492 | + |
---|
| 493 | + if (IS_ERR(dev)) { |
---|
| 494 | + test_err("cannot allocate device"); |
---|
| 495 | + ret = PTR_ERR(dev); |
---|
| 496 | + goto out; |
---|
| 497 | + } |
---|
| 498 | + map->stripes[i].dev = dev; |
---|
| 499 | + map->stripes[i].physical = test->data_stripe_phys_start[i]; |
---|
| 500 | + } |
---|
| 501 | + |
---|
| 502 | + write_lock(&fs_info->mapping_tree.lock); |
---|
| 503 | + ret = add_extent_mapping(&fs_info->mapping_tree, em, 0); |
---|
| 504 | + write_unlock(&fs_info->mapping_tree.lock); |
---|
| 505 | + if (ret) { |
---|
| 506 | + test_err("error adding block group mapping to mapping tree"); |
---|
| 507 | + goto out_free; |
---|
| 508 | + } |
---|
| 509 | + |
---|
| 510 | + ret = btrfs_rmap_block(fs_info, em->start, btrfs_sb_offset(1), |
---|
| 511 | + &logical, &out_ndaddrs, &out_stripe_len); |
---|
| 512 | + if (ret || (out_ndaddrs == 0 && test->expected_mapped_addr)) { |
---|
| 513 | + test_err("didn't rmap anything but expected %d", |
---|
| 514 | + test->expected_mapped_addr); |
---|
| 515 | + goto out; |
---|
| 516 | + } |
---|
| 517 | + |
---|
| 518 | + if (out_stripe_len != BTRFS_STRIPE_LEN) { |
---|
| 519 | + test_err("calculated stripe length doesn't match"); |
---|
| 520 | + goto out; |
---|
| 521 | + } |
---|
| 522 | + |
---|
| 523 | + if (out_ndaddrs != test->expected_mapped_addr) { |
---|
| 524 | + for (i = 0; i < out_ndaddrs; i++) |
---|
| 525 | + test_msg("mapped %llu", logical[i]); |
---|
| 526 | + test_err("unexpected number of mapped addresses: %d", out_ndaddrs); |
---|
| 527 | + goto out; |
---|
| 528 | + } |
---|
| 529 | + |
---|
| 530 | + for (i = 0; i < out_ndaddrs; i++) { |
---|
| 531 | + if (logical[i] != test->mapped_logical[i]) { |
---|
| 532 | + test_err("unexpected logical address mapped"); |
---|
| 533 | + goto out; |
---|
| 534 | + } |
---|
| 535 | + } |
---|
| 536 | + |
---|
| 537 | + ret = 0; |
---|
| 538 | +out: |
---|
| 539 | + write_lock(&fs_info->mapping_tree.lock); |
---|
| 540 | + remove_extent_mapping(&fs_info->mapping_tree, em); |
---|
| 541 | + write_unlock(&fs_info->mapping_tree.lock); |
---|
| 542 | + /* For us */ |
---|
| 543 | + free_extent_map(em); |
---|
| 544 | +out_free: |
---|
| 545 | + /* For the tree */ |
---|
| 546 | + free_extent_map(em); |
---|
| 547 | + kfree(logical); |
---|
| 548 | + return ret; |
---|
337 | 549 | } |
---|
338 | 550 | |
---|
339 | 551 | int btrfs_test_extent_map(void) |
---|
340 | 552 | { |
---|
341 | 553 | struct btrfs_fs_info *fs_info = NULL; |
---|
342 | 554 | struct extent_map_tree *em_tree; |
---|
| 555 | + int ret = 0, i; |
---|
| 556 | + struct rmap_test_vector rmap_tests[] = { |
---|
| 557 | + { |
---|
| 558 | + /* |
---|
| 559 | + * Test a chunk with 2 data stripes one of which |
---|
| 560 | + * interesects the physical address of the super block |
---|
| 561 | + * is correctly recognised. |
---|
| 562 | + */ |
---|
| 563 | + .raid_type = BTRFS_BLOCK_GROUP_RAID1, |
---|
| 564 | + .physical_start = SZ_64M - SZ_4M, |
---|
| 565 | + .data_stripe_size = SZ_256M, |
---|
| 566 | + .num_data_stripes = 2, |
---|
| 567 | + .num_stripes = 2, |
---|
| 568 | + .data_stripe_phys_start = |
---|
| 569 | + {SZ_64M - SZ_4M, SZ_64M - SZ_4M + SZ_256M}, |
---|
| 570 | + .expected_mapped_addr = true, |
---|
| 571 | + .mapped_logical= {SZ_4G + SZ_4M} |
---|
| 572 | + }, |
---|
| 573 | + { |
---|
| 574 | + /* |
---|
| 575 | + * Test that out-of-range physical addresses are |
---|
| 576 | + * ignored |
---|
| 577 | + */ |
---|
| 578 | + |
---|
| 579 | + /* SINGLE chunk type */ |
---|
| 580 | + .raid_type = 0, |
---|
| 581 | + .physical_start = SZ_4G, |
---|
| 582 | + .data_stripe_size = SZ_256M, |
---|
| 583 | + .num_data_stripes = 1, |
---|
| 584 | + .num_stripes = 1, |
---|
| 585 | + .data_stripe_phys_start = {SZ_256M}, |
---|
| 586 | + .expected_mapped_addr = false, |
---|
| 587 | + .mapped_logical = {0} |
---|
| 588 | + } |
---|
| 589 | + }; |
---|
343 | 590 | |
---|
344 | 591 | test_msg("running extent_map tests"); |
---|
345 | 592 | |
---|
.. | .. |
---|
349 | 596 | */ |
---|
350 | 597 | fs_info = btrfs_alloc_dummy_fs_info(PAGE_SIZE, PAGE_SIZE); |
---|
351 | 598 | if (!fs_info) { |
---|
352 | | - test_msg("Couldn't allocate dummy fs info"); |
---|
| 599 | + test_std_err(TEST_ALLOC_FS_INFO); |
---|
353 | 600 | return -ENOMEM; |
---|
354 | 601 | } |
---|
355 | 602 | |
---|
356 | 603 | em_tree = kzalloc(sizeof(*em_tree), GFP_KERNEL); |
---|
357 | | - if (!em_tree) |
---|
358 | | - /* Skip the test on error. */ |
---|
| 604 | + if (!em_tree) { |
---|
| 605 | + ret = -ENOMEM; |
---|
359 | 606 | goto out; |
---|
| 607 | + } |
---|
360 | 608 | |
---|
361 | 609 | extent_map_tree_init(em_tree); |
---|
362 | 610 | |
---|
363 | | - test_case_1(fs_info, em_tree); |
---|
364 | | - test_case_2(fs_info, em_tree); |
---|
365 | | - test_case_3(fs_info, em_tree); |
---|
366 | | - test_case_4(fs_info, em_tree); |
---|
| 611 | + ret = test_case_1(fs_info, em_tree); |
---|
| 612 | + if (ret) |
---|
| 613 | + goto out; |
---|
| 614 | + ret = test_case_2(fs_info, em_tree); |
---|
| 615 | + if (ret) |
---|
| 616 | + goto out; |
---|
| 617 | + ret = test_case_3(fs_info, em_tree); |
---|
| 618 | + if (ret) |
---|
| 619 | + goto out; |
---|
| 620 | + ret = test_case_4(fs_info, em_tree); |
---|
367 | 621 | |
---|
368 | | - kfree(em_tree); |
---|
| 622 | + test_msg("running rmap tests"); |
---|
| 623 | + for (i = 0; i < ARRAY_SIZE(rmap_tests); i++) { |
---|
| 624 | + ret = test_rmap_block(fs_info, &rmap_tests[i]); |
---|
| 625 | + if (ret) |
---|
| 626 | + goto out; |
---|
| 627 | + } |
---|
| 628 | + |
---|
369 | 629 | out: |
---|
| 630 | + kfree(em_tree); |
---|
370 | 631 | btrfs_free_dummy_fs_info(fs_info); |
---|
371 | 632 | |
---|
372 | | - return 0; |
---|
| 633 | + return ret; |
---|
373 | 634 | } |
---|