diff options
-rw-r--r-- | fs/btrfs/tests/free-space-tree-tests.c | 164 |
1 files changed, 96 insertions, 68 deletions
diff --git a/fs/btrfs/tests/free-space-tree-tests.c b/fs/btrfs/tests/free-space-tree-tests.c index 7508d3b42780..c449da4d77b9 100644 --- a/fs/btrfs/tests/free-space-tree-tests.c +++ b/fs/btrfs/tests/free-space-tree-tests.c | |||
@@ -27,12 +27,6 @@ struct free_space_extent { | |||
27 | u64 start, length; | 27 | u64 start, length; |
28 | }; | 28 | }; |
29 | 29 | ||
30 | /* | ||
31 | * The test cases align their operations to this in order to hit some of the | ||
32 | * edge cases in the bitmap code. | ||
33 | */ | ||
34 | #define BITMAP_RANGE (BTRFS_FREE_SPACE_BITMAP_BITS * PAGE_SIZE) | ||
35 | |||
36 | static int __check_free_space_extents(struct btrfs_trans_handle *trans, | 30 | static int __check_free_space_extents(struct btrfs_trans_handle *trans, |
37 | struct btrfs_fs_info *fs_info, | 31 | struct btrfs_fs_info *fs_info, |
38 | struct btrfs_block_group_cache *cache, | 32 | struct btrfs_block_group_cache *cache, |
@@ -168,7 +162,8 @@ static int check_free_space_extents(struct btrfs_trans_handle *trans, | |||
168 | static int test_empty_block_group(struct btrfs_trans_handle *trans, | 162 | static int test_empty_block_group(struct btrfs_trans_handle *trans, |
169 | struct btrfs_fs_info *fs_info, | 163 | struct btrfs_fs_info *fs_info, |
170 | struct btrfs_block_group_cache *cache, | 164 | struct btrfs_block_group_cache *cache, |
171 | struct btrfs_path *path) | 165 | struct btrfs_path *path, |
166 | u32 alignment) | ||
172 | { | 167 | { |
173 | struct free_space_extent extents[] = { | 168 | struct free_space_extent extents[] = { |
174 | {cache->key.objectid, cache->key.offset}, | 169 | {cache->key.objectid, cache->key.offset}, |
@@ -181,7 +176,8 @@ static int test_empty_block_group(struct btrfs_trans_handle *trans, | |||
181 | static int test_remove_all(struct btrfs_trans_handle *trans, | 176 | static int test_remove_all(struct btrfs_trans_handle *trans, |
182 | struct btrfs_fs_info *fs_info, | 177 | struct btrfs_fs_info *fs_info, |
183 | struct btrfs_block_group_cache *cache, | 178 | struct btrfs_block_group_cache *cache, |
184 | struct btrfs_path *path) | 179 | struct btrfs_path *path, |
180 | u32 alignment) | ||
185 | { | 181 | { |
186 | struct free_space_extent extents[] = {}; | 182 | struct free_space_extent extents[] = {}; |
187 | int ret; | 183 | int ret; |
@@ -201,16 +197,17 @@ static int test_remove_all(struct btrfs_trans_handle *trans, | |||
201 | static int test_remove_beginning(struct btrfs_trans_handle *trans, | 197 | static int test_remove_beginning(struct btrfs_trans_handle *trans, |
202 | struct btrfs_fs_info *fs_info, | 198 | struct btrfs_fs_info *fs_info, |
203 | struct btrfs_block_group_cache *cache, | 199 | struct btrfs_block_group_cache *cache, |
204 | struct btrfs_path *path) | 200 | struct btrfs_path *path, |
201 | u32 alignment) | ||
205 | { | 202 | { |
206 | struct free_space_extent extents[] = { | 203 | struct free_space_extent extents[] = { |
207 | {cache->key.objectid + BITMAP_RANGE, | 204 | {cache->key.objectid + alignment, |
208 | cache->key.offset - BITMAP_RANGE}, | 205 | cache->key.offset - alignment}, |
209 | }; | 206 | }; |
210 | int ret; | 207 | int ret; |
211 | 208 | ||
212 | ret = __remove_from_free_space_tree(trans, fs_info, cache, path, | 209 | ret = __remove_from_free_space_tree(trans, fs_info, cache, path, |
213 | cache->key.objectid, BITMAP_RANGE); | 210 | cache->key.objectid, alignment); |
214 | if (ret) { | 211 | if (ret) { |
215 | test_msg("Could not remove free space\n"); | 212 | test_msg("Could not remove free space\n"); |
216 | return ret; | 213 | return ret; |
@@ -224,17 +221,18 @@ static int test_remove_beginning(struct btrfs_trans_handle *trans, | |||
224 | static int test_remove_end(struct btrfs_trans_handle *trans, | 221 | static int test_remove_end(struct btrfs_trans_handle *trans, |
225 | struct btrfs_fs_info *fs_info, | 222 | struct btrfs_fs_info *fs_info, |
226 | struct btrfs_block_group_cache *cache, | 223 | struct btrfs_block_group_cache *cache, |
227 | struct btrfs_path *path) | 224 | struct btrfs_path *path, |
225 | u32 alignment) | ||
228 | { | 226 | { |
229 | struct free_space_extent extents[] = { | 227 | struct free_space_extent extents[] = { |
230 | {cache->key.objectid, cache->key.offset - BITMAP_RANGE}, | 228 | {cache->key.objectid, cache->key.offset - alignment}, |
231 | }; | 229 | }; |
232 | int ret; | 230 | int ret; |
233 | 231 | ||
234 | ret = __remove_from_free_space_tree(trans, fs_info, cache, path, | 232 | ret = __remove_from_free_space_tree(trans, fs_info, cache, path, |
235 | cache->key.objectid + | 233 | cache->key.objectid + |
236 | cache->key.offset - BITMAP_RANGE, | 234 | cache->key.offset - alignment, |
237 | BITMAP_RANGE); | 235 | alignment); |
238 | if (ret) { | 236 | if (ret) { |
239 | test_msg("Could not remove free space\n"); | 237 | test_msg("Could not remove free space\n"); |
240 | return ret; | 238 | return ret; |
@@ -247,18 +245,19 @@ static int test_remove_end(struct btrfs_trans_handle *trans, | |||
247 | static int test_remove_middle(struct btrfs_trans_handle *trans, | 245 | static int test_remove_middle(struct btrfs_trans_handle *trans, |
248 | struct btrfs_fs_info *fs_info, | 246 | struct btrfs_fs_info *fs_info, |
249 | struct btrfs_block_group_cache *cache, | 247 | struct btrfs_block_group_cache *cache, |
250 | struct btrfs_path *path) | 248 | struct btrfs_path *path, |
249 | u32 alignment) | ||
251 | { | 250 | { |
252 | struct free_space_extent extents[] = { | 251 | struct free_space_extent extents[] = { |
253 | {cache->key.objectid, BITMAP_RANGE}, | 252 | {cache->key.objectid, alignment}, |
254 | {cache->key.objectid + 2 * BITMAP_RANGE, | 253 | {cache->key.objectid + 2 * alignment, |
255 | cache->key.offset - 2 * BITMAP_RANGE}, | 254 | cache->key.offset - 2 * alignment}, |
256 | }; | 255 | }; |
257 | int ret; | 256 | int ret; |
258 | 257 | ||
259 | ret = __remove_from_free_space_tree(trans, fs_info, cache, path, | 258 | ret = __remove_from_free_space_tree(trans, fs_info, cache, path, |
260 | cache->key.objectid + BITMAP_RANGE, | 259 | cache->key.objectid + alignment, |
261 | BITMAP_RANGE); | 260 | alignment); |
262 | if (ret) { | 261 | if (ret) { |
263 | test_msg("Could not remove free space\n"); | 262 | test_msg("Could not remove free space\n"); |
264 | return ret; | 263 | return ret; |
@@ -271,10 +270,11 @@ static int test_remove_middle(struct btrfs_trans_handle *trans, | |||
271 | static int test_merge_left(struct btrfs_trans_handle *trans, | 270 | static int test_merge_left(struct btrfs_trans_handle *trans, |
272 | struct btrfs_fs_info *fs_info, | 271 | struct btrfs_fs_info *fs_info, |
273 | struct btrfs_block_group_cache *cache, | 272 | struct btrfs_block_group_cache *cache, |
274 | struct btrfs_path *path) | 273 | struct btrfs_path *path, |
274 | u32 alignment) | ||
275 | { | 275 | { |
276 | struct free_space_extent extents[] = { | 276 | struct free_space_extent extents[] = { |
277 | {cache->key.objectid, 2 * BITMAP_RANGE}, | 277 | {cache->key.objectid, 2 * alignment}, |
278 | }; | 278 | }; |
279 | int ret; | 279 | int ret; |
280 | 280 | ||
@@ -287,15 +287,15 @@ static int test_merge_left(struct btrfs_trans_handle *trans, | |||
287 | } | 287 | } |
288 | 288 | ||
289 | ret = __add_to_free_space_tree(trans, fs_info, cache, path, | 289 | ret = __add_to_free_space_tree(trans, fs_info, cache, path, |
290 | cache->key.objectid, BITMAP_RANGE); | 290 | cache->key.objectid, alignment); |
291 | if (ret) { | 291 | if (ret) { |
292 | test_msg("Could not add free space\n"); | 292 | test_msg("Could not add free space\n"); |
293 | return ret; | 293 | return ret; |
294 | } | 294 | } |
295 | 295 | ||
296 | ret = __add_to_free_space_tree(trans, fs_info, cache, path, | 296 | ret = __add_to_free_space_tree(trans, fs_info, cache, path, |
297 | cache->key.objectid + BITMAP_RANGE, | 297 | cache->key.objectid + alignment, |
298 | BITMAP_RANGE); | 298 | alignment); |
299 | if (ret) { | 299 | if (ret) { |
300 | test_msg("Could not add free space\n"); | 300 | test_msg("Could not add free space\n"); |
301 | return ret; | 301 | return ret; |
@@ -308,10 +308,11 @@ static int test_merge_left(struct btrfs_trans_handle *trans, | |||
308 | static int test_merge_right(struct btrfs_trans_handle *trans, | 308 | static int test_merge_right(struct btrfs_trans_handle *trans, |
309 | struct btrfs_fs_info *fs_info, | 309 | struct btrfs_fs_info *fs_info, |
310 | struct btrfs_block_group_cache *cache, | 310 | struct btrfs_block_group_cache *cache, |
311 | struct btrfs_path *path) | 311 | struct btrfs_path *path, |
312 | u32 alignment) | ||
312 | { | 313 | { |
313 | struct free_space_extent extents[] = { | 314 | struct free_space_extent extents[] = { |
314 | {cache->key.objectid + BITMAP_RANGE, 2 * BITMAP_RANGE}, | 315 | {cache->key.objectid + alignment, 2 * alignment}, |
315 | }; | 316 | }; |
316 | int ret; | 317 | int ret; |
317 | 318 | ||
@@ -324,16 +325,16 @@ static int test_merge_right(struct btrfs_trans_handle *trans, | |||
324 | } | 325 | } |
325 | 326 | ||
326 | ret = __add_to_free_space_tree(trans, fs_info, cache, path, | 327 | ret = __add_to_free_space_tree(trans, fs_info, cache, path, |
327 | cache->key.objectid + 2 * BITMAP_RANGE, | 328 | cache->key.objectid + 2 * alignment, |
328 | BITMAP_RANGE); | 329 | alignment); |
329 | if (ret) { | 330 | if (ret) { |
330 | test_msg("Could not add free space\n"); | 331 | test_msg("Could not add free space\n"); |
331 | return ret; | 332 | return ret; |
332 | } | 333 | } |
333 | 334 | ||
334 | ret = __add_to_free_space_tree(trans, fs_info, cache, path, | 335 | ret = __add_to_free_space_tree(trans, fs_info, cache, path, |
335 | cache->key.objectid + BITMAP_RANGE, | 336 | cache->key.objectid + alignment, |
336 | BITMAP_RANGE); | 337 | alignment); |
337 | if (ret) { | 338 | if (ret) { |
338 | test_msg("Could not add free space\n"); | 339 | test_msg("Could not add free space\n"); |
339 | return ret; | 340 | return ret; |
@@ -346,10 +347,11 @@ static int test_merge_right(struct btrfs_trans_handle *trans, | |||
346 | static int test_merge_both(struct btrfs_trans_handle *trans, | 347 | static int test_merge_both(struct btrfs_trans_handle *trans, |
347 | struct btrfs_fs_info *fs_info, | 348 | struct btrfs_fs_info *fs_info, |
348 | struct btrfs_block_group_cache *cache, | 349 | struct btrfs_block_group_cache *cache, |
349 | struct btrfs_path *path) | 350 | struct btrfs_path *path, |
351 | u32 alignment) | ||
350 | { | 352 | { |
351 | struct free_space_extent extents[] = { | 353 | struct free_space_extent extents[] = { |
352 | {cache->key.objectid, 3 * BITMAP_RANGE}, | 354 | {cache->key.objectid, 3 * alignment}, |
353 | }; | 355 | }; |
354 | int ret; | 356 | int ret; |
355 | 357 | ||
@@ -362,23 +364,23 @@ static int test_merge_both(struct btrfs_trans_handle *trans, | |||
362 | } | 364 | } |
363 | 365 | ||
364 | ret = __add_to_free_space_tree(trans, fs_info, cache, path, | 366 | ret = __add_to_free_space_tree(trans, fs_info, cache, path, |
365 | cache->key.objectid, BITMAP_RANGE); | 367 | cache->key.objectid, alignment); |
366 | if (ret) { | 368 | if (ret) { |
367 | test_msg("Could not add free space\n"); | 369 | test_msg("Could not add free space\n"); |
368 | return ret; | 370 | return ret; |
369 | } | 371 | } |
370 | 372 | ||
371 | ret = __add_to_free_space_tree(trans, fs_info, cache, path, | 373 | ret = __add_to_free_space_tree(trans, fs_info, cache, path, |
372 | cache->key.objectid + 2 * BITMAP_RANGE, | 374 | cache->key.objectid + 2 * alignment, |
373 | BITMAP_RANGE); | 375 | alignment); |
374 | if (ret) { | 376 | if (ret) { |
375 | test_msg("Could not add free space\n"); | 377 | test_msg("Could not add free space\n"); |
376 | return ret; | 378 | return ret; |
377 | } | 379 | } |
378 | 380 | ||
379 | ret = __add_to_free_space_tree(trans, fs_info, cache, path, | 381 | ret = __add_to_free_space_tree(trans, fs_info, cache, path, |
380 | cache->key.objectid + BITMAP_RANGE, | 382 | cache->key.objectid + alignment, |
381 | BITMAP_RANGE); | 383 | alignment); |
382 | if (ret) { | 384 | if (ret) { |
383 | test_msg("Could not add free space\n"); | 385 | test_msg("Could not add free space\n"); |
384 | return ret; | 386 | return ret; |
@@ -391,12 +393,13 @@ static int test_merge_both(struct btrfs_trans_handle *trans, | |||
391 | static int test_merge_none(struct btrfs_trans_handle *trans, | 393 | static int test_merge_none(struct btrfs_trans_handle *trans, |
392 | struct btrfs_fs_info *fs_info, | 394 | struct btrfs_fs_info *fs_info, |
393 | struct btrfs_block_group_cache *cache, | 395 | struct btrfs_block_group_cache *cache, |
394 | struct btrfs_path *path) | 396 | struct btrfs_path *path, |
397 | u32 alignment) | ||
395 | { | 398 | { |
396 | struct free_space_extent extents[] = { | 399 | struct free_space_extent extents[] = { |
397 | {cache->key.objectid, BITMAP_RANGE}, | 400 | {cache->key.objectid, alignment}, |
398 | {cache->key.objectid + 2 * BITMAP_RANGE, BITMAP_RANGE}, | 401 | {cache->key.objectid + 2 * alignment, alignment}, |
399 | {cache->key.objectid + 4 * BITMAP_RANGE, BITMAP_RANGE}, | 402 | {cache->key.objectid + 4 * alignment, alignment}, |
400 | }; | 403 | }; |
401 | int ret; | 404 | int ret; |
402 | 405 | ||
@@ -409,23 +412,23 @@ static int test_merge_none(struct btrfs_trans_handle *trans, | |||
409 | } | 412 | } |
410 | 413 | ||
411 | ret = __add_to_free_space_tree(trans, fs_info, cache, path, | 414 | ret = __add_to_free_space_tree(trans, fs_info, cache, path, |
412 | cache->key.objectid, BITMAP_RANGE); | 415 | cache->key.objectid, alignment); |
413 | if (ret) { | 416 | if (ret) { |
414 | test_msg("Could not add free space\n"); | 417 | test_msg("Could not add free space\n"); |
415 | return ret; | 418 | return ret; |
416 | } | 419 | } |
417 | 420 | ||
418 | ret = __add_to_free_space_tree(trans, fs_info, cache, path, | 421 | ret = __add_to_free_space_tree(trans, fs_info, cache, path, |
419 | cache->key.objectid + 4 * BITMAP_RANGE, | 422 | cache->key.objectid + 4 * alignment, |
420 | BITMAP_RANGE); | 423 | alignment); |
421 | if (ret) { | 424 | if (ret) { |
422 | test_msg("Could not add free space\n"); | 425 | test_msg("Could not add free space\n"); |
423 | return ret; | 426 | return ret; |
424 | } | 427 | } |
425 | 428 | ||
426 | ret = __add_to_free_space_tree(trans, fs_info, cache, path, | 429 | ret = __add_to_free_space_tree(trans, fs_info, cache, path, |
427 | cache->key.objectid + 2 * BITMAP_RANGE, | 430 | cache->key.objectid + 2 * alignment, |
428 | BITMAP_RANGE); | 431 | alignment); |
429 | if (ret) { | 432 | if (ret) { |
430 | test_msg("Could not add free space\n"); | 433 | test_msg("Could not add free space\n"); |
431 | return ret; | 434 | return ret; |
@@ -438,10 +441,11 @@ static int test_merge_none(struct btrfs_trans_handle *trans, | |||
438 | typedef int (*test_func_t)(struct btrfs_trans_handle *, | 441 | typedef int (*test_func_t)(struct btrfs_trans_handle *, |
439 | struct btrfs_fs_info *, | 442 | struct btrfs_fs_info *, |
440 | struct btrfs_block_group_cache *, | 443 | struct btrfs_block_group_cache *, |
441 | struct btrfs_path *); | 444 | struct btrfs_path *, |
445 | u32 alignment); | ||
442 | 446 | ||
443 | static int run_test(test_func_t test_func, int bitmaps, | 447 | static int run_test(test_func_t test_func, int bitmaps, u32 sectorsize, |
444 | u32 sectorsize, u32 nodesize) | 448 | u32 nodesize, u32 alignment) |
445 | { | 449 | { |
446 | struct btrfs_fs_info *fs_info; | 450 | struct btrfs_fs_info *fs_info; |
447 | struct btrfs_root *root = NULL; | 451 | struct btrfs_root *root = NULL; |
@@ -480,7 +484,7 @@ static int run_test(test_func_t test_func, int bitmaps, | |||
480 | btrfs_set_header_nritems(root->node, 0); | 484 | btrfs_set_header_nritems(root->node, 0); |
481 | root->alloc_bytenr += 2 * nodesize; | 485 | root->alloc_bytenr += 2 * nodesize; |
482 | 486 | ||
483 | cache = btrfs_alloc_dummy_block_group(8 * BITMAP_RANGE, sectorsize); | 487 | cache = btrfs_alloc_dummy_block_group(8 * alignment, sectorsize); |
484 | if (!cache) { | 488 | if (!cache) { |
485 | test_msg("Couldn't allocate dummy block group cache\n"); | 489 | test_msg("Couldn't allocate dummy block group cache\n"); |
486 | ret = -ENOMEM; | 490 | ret = -ENOMEM; |
@@ -514,7 +518,7 @@ static int run_test(test_func_t test_func, int bitmaps, | |||
514 | } | 518 | } |
515 | } | 519 | } |
516 | 520 | ||
517 | ret = test_func(&trans, root->fs_info, cache, path); | 521 | ret = test_func(&trans, root->fs_info, cache, path, alignment); |
518 | if (ret) | 522 | if (ret) |
519 | goto out; | 523 | goto out; |
520 | 524 | ||
@@ -539,15 +543,27 @@ out: | |||
539 | return ret; | 543 | return ret; |
540 | } | 544 | } |
541 | 545 | ||
542 | static int run_test_both_formats(test_func_t test_func, | 546 | static int run_test_both_formats(test_func_t test_func, u32 sectorsize, |
543 | u32 sectorsize, u32 nodesize) | 547 | u32 nodesize, u32 alignment) |
544 | { | 548 | { |
549 | int test_ret = 0; | ||
545 | int ret; | 550 | int ret; |
546 | 551 | ||
547 | ret = run_test(test_func, 0, sectorsize, nodesize); | 552 | ret = run_test(test_func, 0, sectorsize, nodesize, alignment); |
548 | if (ret) | 553 | if (ret) { |
549 | return ret; | 554 | test_msg("%pf failed with extents, sectorsize=%u, nodesize=%u, alignment=%u\n", |
550 | return run_test(test_func, 1, sectorsize, nodesize); | 555 | test_func, sectorsize, nodesize, alignment); |
556 | test_ret = ret; | ||
557 | } | ||
558 | |||
559 | ret = run_test(test_func, 1, sectorsize, nodesize, alignment); | ||
560 | if (ret) { | ||
561 | test_msg("%pf failed with bitmaps, sectorsize=%u, nodesize=%u, alignment=%u\n", | ||
562 | test_func, sectorsize, nodesize, alignment); | ||
563 | test_ret = ret; | ||
564 | } | ||
565 | |||
566 | return test_ret; | ||
551 | } | 567 | } |
552 | 568 | ||
553 | int btrfs_test_free_space_tree(u32 sectorsize, u32 nodesize) | 569 | int btrfs_test_free_space_tree(u32 sectorsize, u32 nodesize) |
@@ -563,18 +579,30 @@ int btrfs_test_free_space_tree(u32 sectorsize, u32 nodesize) | |||
563 | test_merge_both, | 579 | test_merge_both, |
564 | test_merge_none, | 580 | test_merge_none, |
565 | }; | 581 | }; |
582 | u32 bitmap_alignment; | ||
583 | int test_ret = 0; | ||
566 | int i; | 584 | int i; |
567 | 585 | ||
586 | /* | ||
587 | * Align some operations to a page to flush out bugs in the extent | ||
588 | * buffer bitmap handling of highmem. | ||
589 | */ | ||
590 | bitmap_alignment = BTRFS_FREE_SPACE_BITMAP_BITS * PAGE_SIZE; | ||
591 | |||
568 | test_msg("Running free space tree tests\n"); | 592 | test_msg("Running free space tree tests\n"); |
569 | for (i = 0; i < ARRAY_SIZE(tests); i++) { | 593 | for (i = 0; i < ARRAY_SIZE(tests); i++) { |
570 | int ret = run_test_both_formats(tests[i], sectorsize, | 594 | int ret; |
571 | nodesize); | 595 | |
572 | if (ret) { | 596 | ret = run_test_both_formats(tests[i], sectorsize, nodesize, |
573 | test_msg("%pf : sectorsize %u failed\n", | 597 | sectorsize); |
574 | tests[i], sectorsize); | 598 | if (ret) |
575 | return ret; | 599 | test_ret = ret; |
576 | } | 600 | |
601 | ret = run_test_both_formats(tests[i], sectorsize, nodesize, | ||
602 | bitmap_alignment); | ||
603 | if (ret) | ||
604 | test_ret = ret; | ||
577 | } | 605 | } |
578 | 606 | ||
579 | return 0; | 607 | return test_ret; |
580 | } | 608 | } |