aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/tests/extent-io-tests.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/tests/extent-io-tests.c')
-rw-r--r--fs/btrfs/tests/extent-io-tests.c117
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,
58static int test_find_delalloc(u32 sectorsize) 59static 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;
258out_bits: 260out_bits:
259 clear_extent_bits(&tmp, 0, total_dirty - 1, (unsigned)-1); 261 clear_extent_bits(tmp, 0, total_dirty - 1, (unsigned)-1);
260out: 262out:
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
437static 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
435int btrfs_test_extent_io(u32 sectorsize, u32 nodesize) 520int 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);
446out: 535out:
447 return ret; 536 return ret;