1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2017 Oracle. All rights reserved.
4 */
5
6 #include <linux/types.h>
7 #include "btrfs-tests.h"
8 #include "../ctree.h"
9 #include "../btrfs_inode.h"
10 #include "../volumes.h"
11 #include "../disk-io.h"
12 #include "../block-group.h"
13
free_extent_map_tree(struct extent_map_tree * em_tree)14 static void free_extent_map_tree(struct extent_map_tree *em_tree)
15 {
16 struct extent_map *em;
17 struct rb_node *node;
18
19 write_lock(&em_tree->lock);
20 while (!RB_EMPTY_ROOT(&em_tree->map.rb_root)) {
21 node = rb_first_cached(&em_tree->map);
22 em = rb_entry(node, struct extent_map, rb_node);
23 remove_extent_mapping(em_tree, em);
24
25 #ifdef CONFIG_BTRFS_DEBUG
26 if (refcount_read(&em->refs) != 1) {
27 test_err(
28 "em leak: em (start 0x%llx len 0x%llx block_start 0x%llx block_len 0x%llx) refs %d",
29 em->start, em->len, em->block_start,
30 em->block_len, refcount_read(&em->refs));
31
32 refcount_set(&em->refs, 1);
33 }
34 #endif
35 free_extent_map(em);
36 }
37 write_unlock(&em_tree->lock);
38 }
39
40 /*
41 * Test scenario:
42 *
43 * Suppose that no extent map has been loaded into memory yet, there is a file
44 * extent [0, 16K), followed by another file extent [16K, 20K), two dio reads
45 * are entering btrfs_get_extent() concurrently, t1 is reading [8K, 16K), t2 is
46 * reading [0, 8K)
47 *
48 * t1 t2
49 * btrfs_get_extent() btrfs_get_extent()
50 * -> lookup_extent_mapping() ->lookup_extent_mapping()
51 * -> add_extent_mapping(0, 16K)
52 * -> return em
53 * ->add_extent_mapping(0, 16K)
54 * -> #handle -EEXIST
55 */
test_case_1(struct btrfs_fs_info * fs_info,struct extent_map_tree * em_tree)56 static int test_case_1(struct btrfs_fs_info *fs_info,
57 struct extent_map_tree *em_tree)
58 {
59 struct extent_map *em;
60 u64 start = 0;
61 u64 len = SZ_8K;
62 int ret;
63
64 em = alloc_extent_map();
65 if (!em) {
66 test_std_err(TEST_ALLOC_EXTENT_MAP);
67 return -ENOMEM;
68 }
69
70 /* Add [0, 16K) */
71 em->start = 0;
72 em->len = SZ_16K;
73 em->block_start = 0;
74 em->block_len = SZ_16K;
75 write_lock(&em_tree->lock);
76 ret = add_extent_mapping(em_tree, em, 0);
77 write_unlock(&em_tree->lock);
78 if (ret < 0) {
79 test_err("cannot add extent range [0, 16K)");
80 goto out;
81 }
82 free_extent_map(em);
83
84 /* Add [16K, 20K) following [0, 16K) */
85 em = alloc_extent_map();
86 if (!em) {
87 test_std_err(TEST_ALLOC_EXTENT_MAP);
88 ret = -ENOMEM;
89 goto out;
90 }
91
92 em->start = SZ_16K;
93 em->len = SZ_4K;
94 em->block_start = SZ_32K; /* avoid merging */
95 em->block_len = SZ_4K;
96 write_lock(&em_tree->lock);
97 ret = add_extent_mapping(em_tree, em, 0);
98 write_unlock(&em_tree->lock);
99 if (ret < 0) {
100 test_err("cannot add extent range [16K, 20K)");
101 goto out;
102 }
103 free_extent_map(em);
104
105 em = alloc_extent_map();
106 if (!em) {
107 test_std_err(TEST_ALLOC_EXTENT_MAP);
108 ret = -ENOMEM;
109 goto out;
110 }
111
112 /* Add [0, 8K), should return [0, 16K) instead. */
113 em->start = start;
114 em->len = len;
115 em->block_start = start;
116 em->block_len = len;
117 write_lock(&em_tree->lock);
118 ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, em->start, em->len);
119 write_unlock(&em_tree->lock);
120 if (ret) {
121 test_err("case1 [%llu %llu]: ret %d", start, start + len, ret);
122 goto out;
123 }
124 if (em &&
125 (em->start != 0 || extent_map_end(em) != SZ_16K ||
126 em->block_start != 0 || em->block_len != SZ_16K)) {
127 test_err(
128 "case1 [%llu %llu]: ret %d return a wrong em (start %llu len %llu block_start %llu block_len %llu",
129 start, start + len, ret, em->start, em->len,
130 em->block_start, em->block_len);
131 ret = -EINVAL;
132 }
133 free_extent_map(em);
134 out:
135 free_extent_map_tree(em_tree);
136
137 return ret;
138 }
139
140 /*
141 * Test scenario:
142 *
143 * Reading the inline ending up with EEXIST, ie. read an inline
144 * extent and discard page cache and read it again.
145 */
test_case_2(struct btrfs_fs_info * fs_info,struct extent_map_tree * em_tree)146 static int test_case_2(struct btrfs_fs_info *fs_info,
147 struct extent_map_tree *em_tree)
148 {
149 struct extent_map *em;
150 int ret;
151
152 em = alloc_extent_map();
153 if (!em) {
154 test_std_err(TEST_ALLOC_EXTENT_MAP);
155 return -ENOMEM;
156 }
157
158 /* Add [0, 1K) */
159 em->start = 0;
160 em->len = SZ_1K;
161 em->block_start = EXTENT_MAP_INLINE;
162 em->block_len = (u64)-1;
163 write_lock(&em_tree->lock);
164 ret = add_extent_mapping(em_tree, em, 0);
165 write_unlock(&em_tree->lock);
166 if (ret < 0) {
167 test_err("cannot add extent range [0, 1K)");
168 goto out;
169 }
170 free_extent_map(em);
171
172 /* Add [4K, 8K) following [0, 1K) */
173 em = alloc_extent_map();
174 if (!em) {
175 test_std_err(TEST_ALLOC_EXTENT_MAP);
176 ret = -ENOMEM;
177 goto out;
178 }
179
180 em->start = SZ_4K;
181 em->len = SZ_4K;
182 em->block_start = SZ_4K;
183 em->block_len = SZ_4K;
184 write_lock(&em_tree->lock);
185 ret = add_extent_mapping(em_tree, em, 0);
186 write_unlock(&em_tree->lock);
187 if (ret < 0) {
188 test_err("cannot add extent range [4K, 8K)");
189 goto out;
190 }
191 free_extent_map(em);
192
193 em = alloc_extent_map();
194 if (!em) {
195 test_std_err(TEST_ALLOC_EXTENT_MAP);
196 ret = -ENOMEM;
197 goto out;
198 }
199
200 /* Add [0, 1K) */
201 em->start = 0;
202 em->len = SZ_1K;
203 em->block_start = EXTENT_MAP_INLINE;
204 em->block_len = (u64)-1;
205 write_lock(&em_tree->lock);
206 ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, em->start, em->len);
207 write_unlock(&em_tree->lock);
208 if (ret) {
209 test_err("case2 [0 1K]: ret %d", ret);
210 goto out;
211 }
212 if (em &&
213 (em->start != 0 || extent_map_end(em) != SZ_1K ||
214 em->block_start != EXTENT_MAP_INLINE || em->block_len != (u64)-1)) {
215 test_err(
216 "case2 [0 1K]: ret %d return a wrong em (start %llu len %llu block_start %llu block_len %llu",
217 ret, em->start, em->len, em->block_start,
218 em->block_len);
219 ret = -EINVAL;
220 }
221 free_extent_map(em);
222 out:
223 free_extent_map_tree(em_tree);
224
225 return ret;
226 }
227
__test_case_3(struct btrfs_fs_info * fs_info,struct extent_map_tree * em_tree,u64 start)228 static int __test_case_3(struct btrfs_fs_info *fs_info,
229 struct extent_map_tree *em_tree, u64 start)
230 {
231 struct extent_map *em;
232 u64 len = SZ_4K;
233 int ret;
234
235 em = alloc_extent_map();
236 if (!em) {
237 test_std_err(TEST_ALLOC_EXTENT_MAP);
238 return -ENOMEM;
239 }
240
241 /* Add [4K, 8K) */
242 em->start = SZ_4K;
243 em->len = SZ_4K;
244 em->block_start = SZ_4K;
245 em->block_len = SZ_4K;
246 write_lock(&em_tree->lock);
247 ret = add_extent_mapping(em_tree, em, 0);
248 write_unlock(&em_tree->lock);
249 if (ret < 0) {
250 test_err("cannot add extent range [4K, 8K)");
251 goto out;
252 }
253 free_extent_map(em);
254
255 em = alloc_extent_map();
256 if (!em) {
257 test_std_err(TEST_ALLOC_EXTENT_MAP);
258 ret = -ENOMEM;
259 goto out;
260 }
261
262 /* Add [0, 16K) */
263 em->start = 0;
264 em->len = SZ_16K;
265 em->block_start = 0;
266 em->block_len = SZ_16K;
267 write_lock(&em_tree->lock);
268 ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, start, len);
269 write_unlock(&em_tree->lock);
270 if (ret) {
271 test_err("case3 [0x%llx 0x%llx): ret %d",
272 start, start + len, ret);
273 goto out;
274 }
275 /*
276 * Since bytes within em are contiguous, em->block_start is identical to
277 * em->start.
278 */
279 if (em &&
280 (start < em->start || start + len > extent_map_end(em) ||
281 em->start != em->block_start || em->len != em->block_len)) {
282 test_err(
283 "case3 [0x%llx 0x%llx): ret %d em (start 0x%llx len 0x%llx block_start 0x%llx block_len 0x%llx)",
284 start, start + len, ret, em->start, em->len,
285 em->block_start, em->block_len);
286 ret = -EINVAL;
287 }
288 free_extent_map(em);
289 out:
290 free_extent_map_tree(em_tree);
291
292 return ret;
293 }
294
295 /*
296 * Test scenario:
297 *
298 * Suppose that no extent map has been loaded into memory yet.
299 * There is a file extent [0, 16K), two jobs are running concurrently
300 * against it, t1 is buffered writing to [4K, 8K) and t2 is doing dio
301 * read from [0, 4K) or [8K, 12K) or [12K, 16K).
302 *
303 * t1 goes ahead of t2 and adds em [4K, 8K) into tree.
304 *
305 * t1 t2
306 * cow_file_range() btrfs_get_extent()
307 * -> lookup_extent_mapping()
308 * -> add_extent_mapping()
309 * -> add_extent_mapping()
310 */
test_case_3(struct btrfs_fs_info * fs_info,struct extent_map_tree * em_tree)311 static int test_case_3(struct btrfs_fs_info *fs_info,
312 struct extent_map_tree *em_tree)
313 {
314 int ret;
315
316 ret = __test_case_3(fs_info, em_tree, 0);
317 if (ret)
318 return ret;
319 ret = __test_case_3(fs_info, em_tree, SZ_8K);
320 if (ret)
321 return ret;
322 ret = __test_case_3(fs_info, em_tree, (12 * SZ_1K));
323
324 return ret;
325 }
326
__test_case_4(struct btrfs_fs_info * fs_info,struct extent_map_tree * em_tree,u64 start)327 static int __test_case_4(struct btrfs_fs_info *fs_info,
328 struct extent_map_tree *em_tree, u64 start)
329 {
330 struct extent_map *em;
331 u64 len = SZ_4K;
332 int ret;
333
334 em = alloc_extent_map();
335 if (!em) {
336 test_std_err(TEST_ALLOC_EXTENT_MAP);
337 return -ENOMEM;
338 }
339
340 /* Add [0K, 8K) */
341 em->start = 0;
342 em->len = SZ_8K;
343 em->block_start = 0;
344 em->block_len = SZ_8K;
345 write_lock(&em_tree->lock);
346 ret = add_extent_mapping(em_tree, em, 0);
347 write_unlock(&em_tree->lock);
348 if (ret < 0) {
349 test_err("cannot add extent range [0, 8K)");
350 goto out;
351 }
352 free_extent_map(em);
353
354 em = alloc_extent_map();
355 if (!em) {
356 test_std_err(TEST_ALLOC_EXTENT_MAP);
357 ret = -ENOMEM;
358 goto out;
359 }
360
361 /* Add [8K, 32K) */
362 em->start = SZ_8K;
363 em->len = 24 * SZ_1K;
364 em->block_start = SZ_16K; /* avoid merging */
365 em->block_len = 24 * SZ_1K;
366 write_lock(&em_tree->lock);
367 ret = add_extent_mapping(em_tree, em, 0);
368 write_unlock(&em_tree->lock);
369 if (ret < 0) {
370 test_err("cannot add extent range [8K, 32K)");
371 goto out;
372 }
373 free_extent_map(em);
374
375 em = alloc_extent_map();
376 if (!em) {
377 test_std_err(TEST_ALLOC_EXTENT_MAP);
378 ret = -ENOMEM;
379 goto out;
380 }
381 /* Add [0K, 32K) */
382 em->start = 0;
383 em->len = SZ_32K;
384 em->block_start = 0;
385 em->block_len = SZ_32K;
386 write_lock(&em_tree->lock);
387 ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, start, len);
388 write_unlock(&em_tree->lock);
389 if (ret) {
390 test_err("case4 [0x%llx 0x%llx): ret %d",
391 start, len, ret);
392 goto out;
393 }
394 if (em && (start < em->start || start + len > extent_map_end(em))) {
395 test_err(
396 "case4 [0x%llx 0x%llx): ret %d, added wrong em (start 0x%llx len 0x%llx block_start 0x%llx block_len 0x%llx)",
397 start, len, ret, em->start, em->len, em->block_start,
398 em->block_len);
399 ret = -EINVAL;
400 }
401 free_extent_map(em);
402 out:
403 free_extent_map_tree(em_tree);
404
405 return ret;
406 }
407
408 /*
409 * Test scenario:
410 *
411 * Suppose that no extent map has been loaded into memory yet.
412 * There is a file extent [0, 32K), two jobs are running concurrently
413 * against it, t1 is doing dio write to [8K, 32K) and t2 is doing dio
414 * read from [0, 4K) or [4K, 8K).
415 *
416 * t1 goes ahead of t2 and splits em [0, 32K) to em [0K, 8K) and [8K 32K).
417 *
418 * t1 t2
419 * btrfs_get_blocks_direct() btrfs_get_blocks_direct()
420 * -> btrfs_get_extent() -> btrfs_get_extent()
421 * -> lookup_extent_mapping()
422 * -> add_extent_mapping() -> lookup_extent_mapping()
423 * # load [0, 32K)
424 * -> btrfs_new_extent_direct()
425 * -> btrfs_drop_extent_cache()
426 * # split [0, 32K)
427 * -> add_extent_mapping()
428 * # add [8K, 32K)
429 * -> add_extent_mapping()
430 * # handle -EEXIST when adding
431 * # [0, 32K)
432 */
test_case_4(struct btrfs_fs_info * fs_info,struct extent_map_tree * em_tree)433 static int test_case_4(struct btrfs_fs_info *fs_info,
434 struct extent_map_tree *em_tree)
435 {
436 int ret;
437
438 ret = __test_case_4(fs_info, em_tree, 0);
439 if (ret)
440 return ret;
441 ret = __test_case_4(fs_info, em_tree, SZ_4K);
442
443 return ret;
444 }
445
add_compressed_extent(struct extent_map_tree * em_tree,u64 start,u64 len,u64 block_start)446 static int add_compressed_extent(struct extent_map_tree *em_tree,
447 u64 start, u64 len, u64 block_start)
448 {
449 struct extent_map *em;
450 int ret;
451
452 em = alloc_extent_map();
453 if (!em) {
454 test_std_err(TEST_ALLOC_EXTENT_MAP);
455 return -ENOMEM;
456 }
457
458 em->start = start;
459 em->len = len;
460 em->block_start = block_start;
461 em->block_len = SZ_4K;
462 set_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
463 write_lock(&em_tree->lock);
464 ret = add_extent_mapping(em_tree, em, 0);
465 write_unlock(&em_tree->lock);
466 free_extent_map(em);
467 if (ret < 0) {
468 test_err("cannot add extent map [%llu, %llu)", start, start + len);
469 return ret;
470 }
471
472 return 0;
473 }
474
475 struct extent_range {
476 u64 start;
477 u64 len;
478 };
479
480 /* The valid states of the tree after every drop, as described below. */
481 struct extent_range valid_ranges[][7] = {
482 {
483 { .start = 0, .len = SZ_8K }, /* [0, 8K) */
484 { .start = SZ_4K * 3, .len = SZ_4K * 3}, /* [12k, 24k) */
485 { .start = SZ_4K * 6, .len = SZ_4K * 3}, /* [24k, 36k) */
486 { .start = SZ_32K + SZ_4K, .len = SZ_4K}, /* [36k, 40k) */
487 { .start = SZ_4K * 10, .len = SZ_4K * 6}, /* [40k, 64k) */
488 },
489 {
490 { .start = 0, .len = SZ_8K }, /* [0, 8K) */
491 { .start = SZ_4K * 5, .len = SZ_4K}, /* [20k, 24k) */
492 { .start = SZ_4K * 6, .len = SZ_4K * 3}, /* [24k, 36k) */
493 { .start = SZ_32K + SZ_4K, .len = SZ_4K}, /* [36k, 40k) */
494 { .start = SZ_4K * 10, .len = SZ_4K * 6}, /* [40k, 64k) */
495 },
496 {
497 { .start = 0, .len = SZ_8K }, /* [0, 8K) */
498 { .start = SZ_4K * 5, .len = SZ_4K}, /* [20k, 24k) */
499 { .start = SZ_4K * 6, .len = SZ_4K}, /* [24k, 28k) */
500 { .start = SZ_32K, .len = SZ_4K}, /* [32k, 36k) */
501 { .start = SZ_32K + SZ_4K, .len = SZ_4K}, /* [36k, 40k) */
502 { .start = SZ_4K * 10, .len = SZ_4K * 6}, /* [40k, 64k) */
503 },
504 {
505 { .start = 0, .len = SZ_8K}, /* [0, 8K) */
506 { .start = SZ_4K * 5, .len = SZ_4K}, /* [20k, 24k) */
507 { .start = SZ_4K * 6, .len = SZ_4K}, /* [24k, 28k) */
508 }
509 };
510
validate_range(struct extent_map_tree * em_tree,int index)511 static int validate_range(struct extent_map_tree *em_tree, int index)
512 {
513 struct rb_node *n;
514 int i;
515
516 for (i = 0, n = rb_first_cached(&em_tree->map);
517 valid_ranges[index][i].len && n;
518 i++, n = rb_next(n)) {
519 struct extent_map *entry = rb_entry(n, struct extent_map, rb_node);
520
521 if (entry->start != valid_ranges[index][i].start) {
522 test_err("mapping has start %llu expected %llu",
523 entry->start, valid_ranges[index][i].start);
524 return -EINVAL;
525 }
526
527 if (entry->len != valid_ranges[index][i].len) {
528 test_err("mapping has len %llu expected %llu",
529 entry->len, valid_ranges[index][i].len);
530 return -EINVAL;
531 }
532 }
533
534 /*
535 * We exited because we don't have any more entries in the extent_map
536 * but we still expect more valid entries.
537 */
538 if (valid_ranges[index][i].len) {
539 test_err("missing an entry");
540 return -EINVAL;
541 }
542
543 /* We exited the loop but still have entries in the extent map. */
544 if (n) {
545 test_err("we have a left over entry in the extent map we didn't expect");
546 return -EINVAL;
547 }
548
549 return 0;
550 }
551
552 /*
553 * Test scenario:
554 *
555 * Test the various edge cases of btrfs_drop_extent_map_range, create the
556 * following ranges
557 *
558 * [0, 12k)[12k, 24k)[24k, 36k)[36k, 40k)[40k,64k)
559 *
560 * And then we'll drop:
561 *
562 * [8k, 12k) - test the single front split
563 * [12k, 20k) - test the single back split
564 * [28k, 32k) - test the double split
565 * [32k, 64k) - test whole em dropping
566 *
567 * They'll have the EXTENT_FLAG_COMPRESSED flag set to keep the em tree from
568 * merging the em's.
569 */
test_case_5(void)570 static int test_case_5(void)
571 {
572 struct extent_map_tree *em_tree;
573 struct inode *inode;
574 u64 start, end;
575 int ret;
576
577 test_msg("Running btrfs_drop_extent_map_range tests");
578
579 inode = btrfs_new_test_inode();
580 if (!inode) {
581 test_std_err(TEST_ALLOC_INODE);
582 return -ENOMEM;
583 }
584
585 em_tree = &BTRFS_I(inode)->extent_tree;
586
587 /* [0, 12k) */
588 ret = add_compressed_extent(em_tree, 0, SZ_4K * 3, 0);
589 if (ret) {
590 test_err("cannot add extent range [0, 12K)");
591 goto out;
592 }
593
594 /* [12k, 24k) */
595 ret = add_compressed_extent(em_tree, SZ_4K * 3, SZ_4K * 3, SZ_4K);
596 if (ret) {
597 test_err("cannot add extent range [12k, 24k)");
598 goto out;
599 }
600
601 /* [24k, 36k) */
602 ret = add_compressed_extent(em_tree, SZ_4K * 6, SZ_4K * 3, SZ_8K);
603 if (ret) {
604 test_err("cannot add extent range [12k, 24k)");
605 goto out;
606 }
607
608 /* [36k, 40k) */
609 ret = add_compressed_extent(em_tree, SZ_32K + SZ_4K, SZ_4K, SZ_4K * 3);
610 if (ret) {
611 test_err("cannot add extent range [12k, 24k)");
612 goto out;
613 }
614
615 /* [40k, 64k) */
616 ret = add_compressed_extent(em_tree, SZ_4K * 10, SZ_4K * 6, SZ_16K);
617 if (ret) {
618 test_err("cannot add extent range [12k, 24k)");
619 goto out;
620 }
621
622 /* Drop [8k, 12k) */
623 start = SZ_8K;
624 end = (3 * SZ_4K) - 1;
625 btrfs_drop_extent_map_range(BTRFS_I(inode), start, end, false);
626 ret = validate_range(&BTRFS_I(inode)->extent_tree, 0);
627 if (ret)
628 goto out;
629
630 /* Drop [12k, 20k) */
631 start = SZ_4K * 3;
632 end = SZ_16K + SZ_4K - 1;
633 btrfs_drop_extent_map_range(BTRFS_I(inode), start, end, false);
634 ret = validate_range(&BTRFS_I(inode)->extent_tree, 1);
635 if (ret)
636 goto out;
637
638 /* Drop [28k, 32k) */
639 start = SZ_32K - SZ_4K;
640 end = SZ_32K - 1;
641 btrfs_drop_extent_map_range(BTRFS_I(inode), start, end, false);
642 ret = validate_range(&BTRFS_I(inode)->extent_tree, 2);
643 if (ret)
644 goto out;
645
646 /* Drop [32k, 64k) */
647 start = SZ_32K;
648 end = SZ_64K - 1;
649 btrfs_drop_extent_map_range(BTRFS_I(inode), start, end, false);
650 ret = validate_range(&BTRFS_I(inode)->extent_tree, 3);
651 if (ret)
652 goto out;
653 out:
654 iput(inode);
655 return ret;
656 }
657
658 /*
659 * Test the btrfs_add_extent_mapping helper which will attempt to create an em
660 * for areas between two existing ems. Validate it doesn't do this when there
661 * are two unmerged em's side by side.
662 */
test_case_6(struct btrfs_fs_info * fs_info,struct extent_map_tree * em_tree)663 static int test_case_6(struct btrfs_fs_info *fs_info, struct extent_map_tree *em_tree)
664 {
665 struct extent_map *em = NULL;
666 int ret;
667
668 ret = add_compressed_extent(em_tree, 0, SZ_4K, 0);
669 if (ret)
670 goto out;
671
672 ret = add_compressed_extent(em_tree, SZ_4K, SZ_4K, 0);
673 if (ret)
674 goto out;
675
676 em = alloc_extent_map();
677 if (!em) {
678 test_std_err(TEST_ALLOC_EXTENT_MAP);
679 return -ENOMEM;
680 }
681
682 em->start = SZ_4K;
683 em->len = SZ_4K;
684 em->block_start = SZ_16K;
685 em->block_len = SZ_16K;
686 write_lock(&em_tree->lock);
687 ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, 0, SZ_8K);
688 write_unlock(&em_tree->lock);
689
690 if (ret != 0) {
691 test_err("got an error when adding our em: %d", ret);
692 goto out;
693 }
694
695 ret = -EINVAL;
696 if (em->start != 0) {
697 test_err("unexpected em->start at %llu, wanted 0", em->start);
698 goto out;
699 }
700 if (em->len != SZ_4K) {
701 test_err("unexpected em->len %llu, expected 4K", em->len);
702 goto out;
703 }
704 ret = 0;
705 out:
706 free_extent_map(em);
707 free_extent_map_tree(em_tree);
708 return ret;
709 }
710
711 /*
712 * Regression test for btrfs_drop_extent_map_range. Calling with skip_pinned ==
713 * true would mess up the start/end calculations and subsequent splits would be
714 * incorrect.
715 */
test_case_7(void)716 static int test_case_7(void)
717 {
718 struct extent_map_tree *em_tree;
719 struct extent_map *em;
720 struct inode *inode;
721 int ret;
722
723 test_msg("Running btrfs_drop_extent_cache with pinned");
724
725 inode = btrfs_new_test_inode();
726 if (!inode) {
727 test_std_err(TEST_ALLOC_INODE);
728 return -ENOMEM;
729 }
730
731 em_tree = &BTRFS_I(inode)->extent_tree;
732
733 em = alloc_extent_map();
734 if (!em) {
735 test_std_err(TEST_ALLOC_EXTENT_MAP);
736 ret = -ENOMEM;
737 goto out;
738 }
739
740 /* [0, 16K), pinned */
741 em->start = 0;
742 em->len = SZ_16K;
743 em->block_start = 0;
744 em->block_len = SZ_4K;
745 set_bit(EXTENT_FLAG_PINNED, &em->flags);
746 write_lock(&em_tree->lock);
747 ret = add_extent_mapping(em_tree, em, 0);
748 write_unlock(&em_tree->lock);
749 if (ret < 0) {
750 test_err("couldn't add extent map");
751 goto out;
752 }
753 free_extent_map(em);
754
755 em = alloc_extent_map();
756 if (!em) {
757 test_std_err(TEST_ALLOC_EXTENT_MAP);
758 ret = -ENOMEM;
759 goto out;
760 }
761
762 /* [32K, 48K), not pinned */
763 em->start = SZ_32K;
764 em->len = SZ_16K;
765 em->block_start = SZ_32K;
766 em->block_len = SZ_16K;
767 write_lock(&em_tree->lock);
768 ret = add_extent_mapping(em_tree, em, 0);
769 write_unlock(&em_tree->lock);
770 if (ret < 0) {
771 test_err("couldn't add extent map");
772 goto out;
773 }
774 free_extent_map(em);
775
776 /*
777 * Drop [0, 36K) This should skip the [0, 4K) extent and then split the
778 * [32K, 48K) extent.
779 */
780 btrfs_drop_extent_map_range(BTRFS_I(inode), 0, (36 * SZ_1K) - 1, true);
781
782 /* Make sure our extent maps look sane. */
783 ret = -EINVAL;
784
785 em = lookup_extent_mapping(em_tree, 0, SZ_16K);
786 if (!em) {
787 test_err("didn't find an em at 0 as expected");
788 goto out;
789 }
790
791 if (em->start != 0) {
792 test_err("em->start is %llu, expected 0", em->start);
793 goto out;
794 }
795
796 if (em->len != SZ_16K) {
797 test_err("em->len is %llu, expected 16K", em->len);
798 goto out;
799 }
800
801 free_extent_map(em);
802
803 read_lock(&em_tree->lock);
804 em = lookup_extent_mapping(em_tree, SZ_16K, SZ_16K);
805 read_unlock(&em_tree->lock);
806 if (em) {
807 test_err("found an em when we weren't expecting one");
808 goto out;
809 }
810
811 read_lock(&em_tree->lock);
812 em = lookup_extent_mapping(em_tree, SZ_32K, SZ_16K);
813 read_unlock(&em_tree->lock);
814 if (!em) {
815 test_err("didn't find an em at 32K as expected");
816 goto out;
817 }
818
819 if (em->start != (36 * SZ_1K)) {
820 test_err("em->start is %llu, expected 36K", em->start);
821 goto out;
822 }
823
824 if (em->len != (12 * SZ_1K)) {
825 test_err("em->len is %llu, expected 12K", em->len);
826 goto out;
827 }
828
829 if (em->block_start != SZ_32K + SZ_4K) {
830 test_err("em->block_start is %llu, expected 36K", em->block_start);
831 goto out;
832 }
833
834 free_extent_map(em);
835
836 read_lock(&em_tree->lock);
837 em = lookup_extent_mapping(em_tree, 48 * SZ_1K, (u64)-1);
838 read_unlock(&em_tree->lock);
839 if (em) {
840 test_err("found an unexpected em above 48K");
841 goto out;
842 }
843
844 ret = 0;
845 out:
846 free_extent_map(em);
847 iput(inode);
848 return ret;
849 }
850
851 struct rmap_test_vector {
852 u64 raid_type;
853 u64 physical_start;
854 u64 data_stripe_size;
855 u64 num_data_stripes;
856 u64 num_stripes;
857 /* Assume we won't have more than 5 physical stripes */
858 u64 data_stripe_phys_start[5];
859 bool expected_mapped_addr;
860 /* Physical to logical addresses */
861 u64 mapped_logical[5];
862 };
863
test_rmap_block(struct btrfs_fs_info * fs_info,struct rmap_test_vector * test)864 static int test_rmap_block(struct btrfs_fs_info *fs_info,
865 struct rmap_test_vector *test)
866 {
867 struct extent_map *em;
868 struct map_lookup *map = NULL;
869 u64 *logical = NULL;
870 int i, out_ndaddrs, out_stripe_len;
871 int ret;
872
873 em = alloc_extent_map();
874 if (!em) {
875 test_std_err(TEST_ALLOC_EXTENT_MAP);
876 return -ENOMEM;
877 }
878
879 map = kmalloc(map_lookup_size(test->num_stripes), GFP_KERNEL);
880 if (!map) {
881 kfree(em);
882 test_std_err(TEST_ALLOC_EXTENT_MAP);
883 return -ENOMEM;
884 }
885
886 set_bit(EXTENT_FLAG_FS_MAPPING, &em->flags);
887 /* Start at 4GiB logical address */
888 em->start = SZ_4G;
889 em->len = test->data_stripe_size * test->num_data_stripes;
890 em->block_len = em->len;
891 em->orig_block_len = test->data_stripe_size;
892 em->map_lookup = map;
893
894 map->num_stripes = test->num_stripes;
895 map->type = test->raid_type;
896
897 for (i = 0; i < map->num_stripes; i++) {
898 struct btrfs_device *dev = btrfs_alloc_dummy_device(fs_info);
899
900 if (IS_ERR(dev)) {
901 test_err("cannot allocate device");
902 ret = PTR_ERR(dev);
903 goto out;
904 }
905 map->stripes[i].dev = dev;
906 map->stripes[i].physical = test->data_stripe_phys_start[i];
907 }
908
909 write_lock(&fs_info->mapping_tree.lock);
910 ret = add_extent_mapping(&fs_info->mapping_tree, em, 0);
911 write_unlock(&fs_info->mapping_tree.lock);
912 if (ret) {
913 test_err("error adding block group mapping to mapping tree");
914 goto out_free;
915 }
916
917 ret = btrfs_rmap_block(fs_info, em->start, btrfs_sb_offset(1),
918 &logical, &out_ndaddrs, &out_stripe_len);
919 if (ret || (out_ndaddrs == 0 && test->expected_mapped_addr)) {
920 test_err("didn't rmap anything but expected %d",
921 test->expected_mapped_addr);
922 goto out;
923 }
924
925 if (out_stripe_len != BTRFS_STRIPE_LEN) {
926 test_err("calculated stripe length doesn't match");
927 goto out;
928 }
929
930 if (out_ndaddrs != test->expected_mapped_addr) {
931 for (i = 0; i < out_ndaddrs; i++)
932 test_msg("mapped %llu", logical[i]);
933 test_err("unexpected number of mapped addresses: %d", out_ndaddrs);
934 goto out;
935 }
936
937 for (i = 0; i < out_ndaddrs; i++) {
938 if (logical[i] != test->mapped_logical[i]) {
939 test_err("unexpected logical address mapped");
940 goto out;
941 }
942 }
943
944 ret = 0;
945 out:
946 write_lock(&fs_info->mapping_tree.lock);
947 remove_extent_mapping(&fs_info->mapping_tree, em);
948 write_unlock(&fs_info->mapping_tree.lock);
949 /* For us */
950 free_extent_map(em);
951 out_free:
952 /* For the tree */
953 free_extent_map(em);
954 kfree(logical);
955 return ret;
956 }
957
btrfs_test_extent_map(void)958 int btrfs_test_extent_map(void)
959 {
960 struct btrfs_fs_info *fs_info = NULL;
961 struct extent_map_tree *em_tree;
962 int ret = 0, i;
963 struct rmap_test_vector rmap_tests[] = {
964 {
965 /*
966 * Test a chunk with 2 data stripes one of which
967 * intersects the physical address of the super block
968 * is correctly recognised.
969 */
970 .raid_type = BTRFS_BLOCK_GROUP_RAID1,
971 .physical_start = SZ_64M - SZ_4M,
972 .data_stripe_size = SZ_256M,
973 .num_data_stripes = 2,
974 .num_stripes = 2,
975 .data_stripe_phys_start =
976 {SZ_64M - SZ_4M, SZ_64M - SZ_4M + SZ_256M},
977 .expected_mapped_addr = true,
978 .mapped_logical= {SZ_4G + SZ_4M}
979 },
980 {
981 /*
982 * Test that out-of-range physical addresses are
983 * ignored
984 */
985
986 /* SINGLE chunk type */
987 .raid_type = 0,
988 .physical_start = SZ_4G,
989 .data_stripe_size = SZ_256M,
990 .num_data_stripes = 1,
991 .num_stripes = 1,
992 .data_stripe_phys_start = {SZ_256M},
993 .expected_mapped_addr = false,
994 .mapped_logical = {0}
995 }
996 };
997
998 test_msg("running extent_map tests");
999
1000 /*
1001 * Note: the fs_info is not set up completely, we only need
1002 * fs_info::fsid for the tracepoint.
1003 */
1004 fs_info = btrfs_alloc_dummy_fs_info(PAGE_SIZE, PAGE_SIZE);
1005 if (!fs_info) {
1006 test_std_err(TEST_ALLOC_FS_INFO);
1007 return -ENOMEM;
1008 }
1009
1010 em_tree = kzalloc(sizeof(*em_tree), GFP_KERNEL);
1011 if (!em_tree) {
1012 ret = -ENOMEM;
1013 goto out;
1014 }
1015
1016 extent_map_tree_init(em_tree);
1017
1018 ret = test_case_1(fs_info, em_tree);
1019 if (ret)
1020 goto out;
1021 ret = test_case_2(fs_info, em_tree);
1022 if (ret)
1023 goto out;
1024 ret = test_case_3(fs_info, em_tree);
1025 if (ret)
1026 goto out;
1027 ret = test_case_4(fs_info, em_tree);
1028 if (ret)
1029 goto out;
1030 ret = test_case_5();
1031 if (ret)
1032 goto out;
1033 ret = test_case_6(fs_info, em_tree);
1034 if (ret)
1035 goto out;
1036 ret = test_case_7();
1037 if (ret)
1038 goto out;
1039
1040 test_msg("running rmap tests");
1041 for (i = 0; i < ARRAY_SIZE(rmap_tests); i++) {
1042 ret = test_rmap_block(fs_info, &rmap_tests[i]);
1043 if (ret)
1044 goto out;
1045 }
1046
1047 out:
1048 kfree(em_tree);
1049 btrfs_free_dummy_fs_info(fs_info);
1050
1051 return ret;
1052 }
1053