aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/tests/free-space-tree-tests.c164
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
36static int __check_free_space_extents(struct btrfs_trans_handle *trans, 30static 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,
168static int test_empty_block_group(struct btrfs_trans_handle *trans, 162static 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,
181static int test_remove_all(struct btrfs_trans_handle *trans, 176static 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,
201static int test_remove_beginning(struct btrfs_trans_handle *trans, 197static 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,
224static int test_remove_end(struct btrfs_trans_handle *trans, 221static 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,
247static int test_remove_middle(struct btrfs_trans_handle *trans, 245static 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,
271static int test_merge_left(struct btrfs_trans_handle *trans, 270static 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,
308static int test_merge_right(struct btrfs_trans_handle *trans, 308static 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,
346static int test_merge_both(struct btrfs_trans_handle *trans, 347static 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,
391static int test_merge_none(struct btrfs_trans_handle *trans, 393static 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,
438typedef int (*test_func_t)(struct btrfs_trans_handle *, 441typedef 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
443static int run_test(test_func_t test_func, int bitmaps, 447static 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
542static int run_test_both_formats(test_func_t test_func, 546static 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
553int btrfs_test_free_space_tree(u32 sectorsize, u32 nodesize) 569int 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}