diff options
Diffstat (limited to 'fs/btrfs/tests/extent-io-tests.c')
-rw-r--r-- | fs/btrfs/tests/extent-io-tests.c | 117 |
1 files changed, 103 insertions, 14 deletions
diff --git a/fs/btrfs/tests/extent-io-tests.c b/fs/btrfs/tests/extent-io-tests.c index 7bf4d5734dbe..1bf6b5a79191 100644 --- a/fs/btrfs/tests/extent-io-tests.c +++ b/fs/btrfs/tests/extent-io-tests.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include "btrfs-tests.h" | 10 | #include "btrfs-tests.h" |
11 | #include "../ctree.h" | 11 | #include "../ctree.h" |
12 | #include "../extent_io.h" | 12 | #include "../extent_io.h" |
13 | #include "../btrfs_inode.h" | ||
13 | 14 | ||
14 | #define PROCESS_UNLOCK (1 << 0) | 15 | #define PROCESS_UNLOCK (1 << 0) |
15 | #define PROCESS_RELEASE (1 << 1) | 16 | #define PROCESS_RELEASE (1 << 1) |
@@ -58,7 +59,7 @@ static noinline int process_page_range(struct inode *inode, u64 start, u64 end, | |||
58 | static int test_find_delalloc(u32 sectorsize) | 59 | static int test_find_delalloc(u32 sectorsize) |
59 | { | 60 | { |
60 | struct inode *inode; | 61 | struct inode *inode; |
61 | struct extent_io_tree tmp; | 62 | struct extent_io_tree *tmp; |
62 | struct page *page; | 63 | struct page *page; |
63 | struct page *locked_page = NULL; | 64 | struct page *locked_page = NULL; |
64 | unsigned long index = 0; | 65 | unsigned long index = 0; |
@@ -76,12 +77,13 @@ static int test_find_delalloc(u32 sectorsize) | |||
76 | test_std_err(TEST_ALLOC_INODE); | 77 | test_std_err(TEST_ALLOC_INODE); |
77 | return -ENOMEM; | 78 | return -ENOMEM; |
78 | } | 79 | } |
80 | tmp = &BTRFS_I(inode)->io_tree; | ||
79 | 81 | ||
80 | /* | 82 | /* |
81 | * Passing NULL as we don't have fs_info but tracepoints are not used | 83 | * Passing NULL as we don't have fs_info but tracepoints are not used |
82 | * at this point | 84 | * at this point |
83 | */ | 85 | */ |
84 | extent_io_tree_init(NULL, &tmp, IO_TREE_SELFTEST, NULL); | 86 | extent_io_tree_init(NULL, tmp, IO_TREE_SELFTEST, NULL); |
85 | 87 | ||
86 | /* | 88 | /* |
87 | * First go through and create and mark all of our pages dirty, we pin | 89 | * First go through and create and mark all of our pages dirty, we pin |
@@ -108,10 +110,10 @@ static int test_find_delalloc(u32 sectorsize) | |||
108 | * |--- delalloc ---| | 110 | * |--- delalloc ---| |
109 | * |--- search ---| | 111 | * |--- search ---| |
110 | */ | 112 | */ |
111 | set_extent_delalloc(&tmp, 0, sectorsize - 1, 0, NULL); | 113 | set_extent_delalloc(tmp, 0, sectorsize - 1, 0, NULL); |
112 | start = 0; | 114 | start = 0; |
113 | end = 0; | 115 | end = 0; |
114 | found = find_lock_delalloc_range(inode, &tmp, locked_page, &start, | 116 | found = find_lock_delalloc_range(inode, locked_page, &start, |
115 | &end); | 117 | &end); |
116 | if (!found) { | 118 | if (!found) { |
117 | test_err("should have found at least one delalloc"); | 119 | test_err("should have found at least one delalloc"); |
@@ -122,7 +124,7 @@ static int test_find_delalloc(u32 sectorsize) | |||
122 | sectorsize - 1, start, end); | 124 | sectorsize - 1, start, end); |
123 | goto out_bits; | 125 | goto out_bits; |
124 | } | 126 | } |
125 | unlock_extent(&tmp, start, end); | 127 | unlock_extent(tmp, start, end); |
126 | unlock_page(locked_page); | 128 | unlock_page(locked_page); |
127 | put_page(locked_page); | 129 | put_page(locked_page); |
128 | 130 | ||
@@ -139,10 +141,10 @@ static int test_find_delalloc(u32 sectorsize) | |||
139 | test_err("couldn't find the locked page"); | 141 | test_err("couldn't find the locked page"); |
140 | goto out_bits; | 142 | goto out_bits; |
141 | } | 143 | } |
142 | set_extent_delalloc(&tmp, sectorsize, max_bytes - 1, 0, NULL); | 144 | set_extent_delalloc(tmp, sectorsize, max_bytes - 1, 0, NULL); |
143 | start = test_start; | 145 | start = test_start; |
144 | end = 0; | 146 | end = 0; |
145 | found = find_lock_delalloc_range(inode, &tmp, locked_page, &start, | 147 | found = find_lock_delalloc_range(inode, locked_page, &start, |
146 | &end); | 148 | &end); |
147 | if (!found) { | 149 | if (!found) { |
148 | test_err("couldn't find delalloc in our range"); | 150 | test_err("couldn't find delalloc in our range"); |
@@ -158,7 +160,7 @@ static int test_find_delalloc(u32 sectorsize) | |||
158 | test_err("there were unlocked pages in the range"); | 160 | test_err("there were unlocked pages in the range"); |
159 | goto out_bits; | 161 | goto out_bits; |
160 | } | 162 | } |
161 | unlock_extent(&tmp, start, end); | 163 | unlock_extent(tmp, start, end); |
162 | /* locked_page was unlocked above */ | 164 | /* locked_page was unlocked above */ |
163 | put_page(locked_page); | 165 | put_page(locked_page); |
164 | 166 | ||
@@ -176,7 +178,7 @@ static int test_find_delalloc(u32 sectorsize) | |||
176 | } | 178 | } |
177 | start = test_start; | 179 | start = test_start; |
178 | end = 0; | 180 | end = 0; |
179 | found = find_lock_delalloc_range(inode, &tmp, locked_page, &start, | 181 | found = find_lock_delalloc_range(inode, locked_page, &start, |
180 | &end); | 182 | &end); |
181 | if (found) { | 183 | if (found) { |
182 | test_err("found range when we shouldn't have"); | 184 | test_err("found range when we shouldn't have"); |
@@ -194,10 +196,10 @@ static int test_find_delalloc(u32 sectorsize) | |||
194 | * | 196 | * |
195 | * We are re-using our test_start from above since it works out well. | 197 | * We are re-using our test_start from above since it works out well. |
196 | */ | 198 | */ |
197 | set_extent_delalloc(&tmp, max_bytes, total_dirty - 1, 0, NULL); | 199 | set_extent_delalloc(tmp, max_bytes, total_dirty - 1, 0, NULL); |
198 | start = test_start; | 200 | start = test_start; |
199 | end = 0; | 201 | end = 0; |
200 | found = find_lock_delalloc_range(inode, &tmp, locked_page, &start, | 202 | found = find_lock_delalloc_range(inode, locked_page, &start, |
201 | &end); | 203 | &end); |
202 | if (!found) { | 204 | if (!found) { |
203 | test_err("didn't find our range"); | 205 | test_err("didn't find our range"); |
@@ -213,7 +215,7 @@ static int test_find_delalloc(u32 sectorsize) | |||
213 | test_err("pages in range were not all locked"); | 215 | test_err("pages in range were not all locked"); |
214 | goto out_bits; | 216 | goto out_bits; |
215 | } | 217 | } |
216 | unlock_extent(&tmp, start, end); | 218 | unlock_extent(tmp, start, end); |
217 | 219 | ||
218 | /* | 220 | /* |
219 | * Now to test where we run into a page that is no longer dirty in the | 221 | * Now to test where we run into a page that is no longer dirty in the |
@@ -238,7 +240,7 @@ static int test_find_delalloc(u32 sectorsize) | |||
238 | * this changes at any point in the future we will need to fix this | 240 | * this changes at any point in the future we will need to fix this |
239 | * tests expected behavior. | 241 | * tests expected behavior. |
240 | */ | 242 | */ |
241 | found = find_lock_delalloc_range(inode, &tmp, locked_page, &start, | 243 | found = find_lock_delalloc_range(inode, locked_page, &start, |
242 | &end); | 244 | &end); |
243 | if (!found) { | 245 | if (!found) { |
244 | test_err("didn't find our range"); | 246 | test_err("didn't find our range"); |
@@ -256,7 +258,7 @@ static int test_find_delalloc(u32 sectorsize) | |||
256 | } | 258 | } |
257 | ret = 0; | 259 | ret = 0; |
258 | out_bits: | 260 | out_bits: |
259 | clear_extent_bits(&tmp, 0, total_dirty - 1, (unsigned)-1); | 261 | clear_extent_bits(tmp, 0, total_dirty - 1, (unsigned)-1); |
260 | out: | 262 | out: |
261 | if (locked_page) | 263 | if (locked_page) |
262 | put_page(locked_page); | 264 | put_page(locked_page); |
@@ -432,6 +434,89 @@ out: | |||
432 | return ret; | 434 | return ret; |
433 | } | 435 | } |
434 | 436 | ||
437 | static int test_find_first_clear_extent_bit(void) | ||
438 | { | ||
439 | struct extent_io_tree tree; | ||
440 | u64 start, end; | ||
441 | |||
442 | test_msg("running find_first_clear_extent_bit test"); | ||
443 | extent_io_tree_init(NULL, &tree, IO_TREE_SELFTEST, NULL); | ||
444 | |||
445 | /* | ||
446 | * Set 1M-4M alloc/discard and 32M-64M thus leaving a hole between | ||
447 | * 4M-32M | ||
448 | */ | ||
449 | set_extent_bits(&tree, SZ_1M, SZ_4M - 1, | ||
450 | CHUNK_TRIMMED | CHUNK_ALLOCATED); | ||
451 | |||
452 | find_first_clear_extent_bit(&tree, SZ_512K, &start, &end, | ||
453 | CHUNK_TRIMMED | CHUNK_ALLOCATED); | ||
454 | |||
455 | if (start != 0 || end != SZ_1M -1) | ||
456 | test_err("error finding beginning range: start %llu end %llu", | ||
457 | start, end); | ||
458 | |||
459 | /* Now add 32M-64M so that we have a hole between 4M-32M */ | ||
460 | set_extent_bits(&tree, SZ_32M, SZ_64M - 1, | ||
461 | CHUNK_TRIMMED | CHUNK_ALLOCATED); | ||
462 | |||
463 | /* | ||
464 | * Request first hole starting at 12M, we should get 4M-32M | ||
465 | */ | ||
466 | find_first_clear_extent_bit(&tree, 12 * SZ_1M, &start, &end, | ||
467 | CHUNK_TRIMMED | CHUNK_ALLOCATED); | ||
468 | |||
469 | if (start != SZ_4M || end != SZ_32M - 1) | ||
470 | test_err("error finding trimmed range: start %llu end %llu", | ||
471 | start, end); | ||
472 | |||
473 | /* | ||
474 | * Search in the middle of allocated range, should get the next one | ||
475 | * available, which happens to be unallocated -> 4M-32M | ||
476 | */ | ||
477 | find_first_clear_extent_bit(&tree, SZ_2M, &start, &end, | ||
478 | CHUNK_TRIMMED | CHUNK_ALLOCATED); | ||
479 | |||
480 | if (start != SZ_4M || end != SZ_32M -1) | ||
481 | test_err("error finding next unalloc range: start %llu end %llu", | ||
482 | start, end); | ||
483 | |||
484 | /* | ||
485 | * Set 64M-72M with CHUNK_ALLOC flag, then search for CHUNK_TRIMMED flag | ||
486 | * being unset in this range, we should get the entry in range 64M-72M | ||
487 | */ | ||
488 | set_extent_bits(&tree, SZ_64M, SZ_64M + SZ_8M - 1, CHUNK_ALLOCATED); | ||
489 | find_first_clear_extent_bit(&tree, SZ_64M + SZ_1M, &start, &end, | ||
490 | CHUNK_TRIMMED); | ||
491 | |||
492 | if (start != SZ_64M || end != SZ_64M + SZ_8M - 1) | ||
493 | test_err("error finding exact range: start %llu end %llu", | ||
494 | start, end); | ||
495 | |||
496 | find_first_clear_extent_bit(&tree, SZ_64M - SZ_8M, &start, &end, | ||
497 | CHUNK_TRIMMED); | ||
498 | |||
499 | /* | ||
500 | * Search in the middle of set range whose immediate neighbour doesn't | ||
501 | * have the bits set so it must be returned | ||
502 | */ | ||
503 | if (start != SZ_64M || end != SZ_64M + SZ_8M - 1) | ||
504 | test_err("error finding next alloc range: start %llu end %llu", | ||
505 | start, end); | ||
506 | |||
507 | /* | ||
508 | * Search beyond any known range, shall return after last known range | ||
509 | * and end should be -1 | ||
510 | */ | ||
511 | find_first_clear_extent_bit(&tree, -1, &start, &end, CHUNK_TRIMMED); | ||
512 | if (start != SZ_64M + SZ_8M || end != -1) | ||
513 | test_err( | ||
514 | "error handling beyond end of range search: start %llu end %llu", | ||
515 | start, end); | ||
516 | |||
517 | return 0; | ||
518 | } | ||
519 | |||
435 | int btrfs_test_extent_io(u32 sectorsize, u32 nodesize) | 520 | int btrfs_test_extent_io(u32 sectorsize, u32 nodesize) |
436 | { | 521 | { |
437 | int ret; | 522 | int ret; |
@@ -442,6 +527,10 @@ int btrfs_test_extent_io(u32 sectorsize, u32 nodesize) | |||
442 | if (ret) | 527 | if (ret) |
443 | goto out; | 528 | goto out; |
444 | 529 | ||
530 | ret = test_find_first_clear_extent_bit(); | ||
531 | if (ret) | ||
532 | goto out; | ||
533 | |||
445 | ret = test_eb_bitmaps(sectorsize, nodesize); | 534 | ret = test_eb_bitmaps(sectorsize, nodesize); |
446 | out: | 535 | out: |
447 | return ret; | 536 | return ret; |