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