1c1d7c514SDavid Sterba // SPDX-License-Identifier: GPL-2.0 272b28077SLiu Bo /* 372b28077SLiu Bo * Copyright (C) 2017 Oracle. All rights reserved. 472b28077SLiu Bo */ 572b28077SLiu Bo 672b28077SLiu Bo #include <linux/types.h> 772b28077SLiu Bo #include "btrfs-tests.h" 872b28077SLiu Bo #include "../ctree.h" 989c37604SJosef Bacik #include "../btrfs_inode.h" 10bf2e2eb0SNikolay Borisov #include "../volumes.h" 11bf2e2eb0SNikolay Borisov #include "../disk-io.h" 12bf2e2eb0SNikolay Borisov #include "../block-group.h" 1372b28077SLiu Bo 1472b28077SLiu Bo static void free_extent_map_tree(struct extent_map_tree *em_tree) 1572b28077SLiu Bo { 1672b28077SLiu Bo struct extent_map *em; 1772b28077SLiu Bo struct rb_node *node; 1872b28077SLiu Bo 196d3b050eSFilipe Manana write_lock(&em_tree->lock); 2007e1ce09SLiu Bo while (!RB_EMPTY_ROOT(&em_tree->map.rb_root)) { 2107e1ce09SLiu Bo node = rb_first_cached(&em_tree->map); 2272b28077SLiu Bo em = rb_entry(node, struct extent_map, rb_node); 2372b28077SLiu Bo remove_extent_mapping(em_tree, em); 2472b28077SLiu Bo 2572b28077SLiu Bo #ifdef CONFIG_BTRFS_DEBUG 2672b28077SLiu Bo if (refcount_read(&em->refs) != 1) { 273c7251f2SDavid Sterba test_err( 283c7251f2SDavid Sterba "em leak: em (start 0x%llx len 0x%llx block_start 0x%llx block_len 0x%llx) refs %d", 2972b28077SLiu Bo em->start, em->len, em->block_start, 3072b28077SLiu Bo em->block_len, refcount_read(&em->refs)); 3172b28077SLiu Bo 3272b28077SLiu Bo refcount_set(&em->refs, 1); 3372b28077SLiu Bo } 3472b28077SLiu Bo #endif 3572b28077SLiu Bo free_extent_map(em); 3672b28077SLiu Bo } 376d3b050eSFilipe Manana write_unlock(&em_tree->lock); 3872b28077SLiu Bo } 3972b28077SLiu Bo 4072b28077SLiu Bo /* 4172b28077SLiu Bo * Test scenario: 4272b28077SLiu Bo * 4372b28077SLiu Bo * Suppose that no extent map has been loaded into memory yet, there is a file 4472b28077SLiu Bo * extent [0, 16K), followed by another file extent [16K, 20K), two dio reads 4572b28077SLiu Bo * are entering btrfs_get_extent() concurrently, t1 is reading [8K, 16K), t2 is 4672b28077SLiu Bo * reading [0, 8K) 4772b28077SLiu Bo * 4872b28077SLiu Bo * t1 t2 4972b28077SLiu Bo * btrfs_get_extent() btrfs_get_extent() 5072b28077SLiu Bo * -> lookup_extent_mapping() ->lookup_extent_mapping() 5172b28077SLiu Bo * -> add_extent_mapping(0, 16K) 5272b28077SLiu Bo * -> return em 5372b28077SLiu Bo * ->add_extent_mapping(0, 16K) 5472b28077SLiu Bo * -> #handle -EEXIST 5572b28077SLiu Bo */ 56488f6730SDavid Sterba static int test_case_1(struct btrfs_fs_info *fs_info, 570e08eb9bSDavid Sterba struct extent_map_tree *em_tree) 5872b28077SLiu Bo { 5972b28077SLiu Bo struct extent_map *em; 6072b28077SLiu Bo u64 start = 0; 6172b28077SLiu Bo u64 len = SZ_8K; 6272b28077SLiu Bo int ret; 6372b28077SLiu Bo 6472b28077SLiu Bo em = alloc_extent_map(); 656c304746SDavid Sterba if (!em) { 666c304746SDavid Sterba test_std_err(TEST_ALLOC_EXTENT_MAP); 67488f6730SDavid Sterba return -ENOMEM; 686c304746SDavid Sterba } 6972b28077SLiu Bo 7072b28077SLiu Bo /* Add [0, 16K) */ 7172b28077SLiu Bo em->start = 0; 7272b28077SLiu Bo em->len = SZ_16K; 7372b28077SLiu Bo em->block_start = 0; 7472b28077SLiu Bo em->block_len = SZ_16K; 7593ead46bSDavid Sterba write_lock(&em_tree->lock); 7672b28077SLiu Bo ret = add_extent_mapping(em_tree, em, 0); 7793ead46bSDavid Sterba write_unlock(&em_tree->lock); 78d7de4b08SDavid Sterba if (ret < 0) { 79d7de4b08SDavid Sterba test_err("cannot add extent range [0, 16K)"); 80d7de4b08SDavid Sterba goto out; 81d7de4b08SDavid Sterba } 8272b28077SLiu Bo free_extent_map(em); 8372b28077SLiu Bo 8472b28077SLiu Bo /* Add [16K, 20K) following [0, 16K) */ 8572b28077SLiu Bo em = alloc_extent_map(); 86488f6730SDavid Sterba if (!em) { 876c304746SDavid Sterba test_std_err(TEST_ALLOC_EXTENT_MAP); 88488f6730SDavid Sterba ret = -ENOMEM; 8972b28077SLiu Bo goto out; 90488f6730SDavid Sterba } 9172b28077SLiu Bo 9272b28077SLiu Bo em->start = SZ_16K; 9372b28077SLiu Bo em->len = SZ_4K; 9472b28077SLiu Bo em->block_start = SZ_32K; /* avoid merging */ 9572b28077SLiu Bo em->block_len = SZ_4K; 9693ead46bSDavid Sterba write_lock(&em_tree->lock); 9772b28077SLiu Bo ret = add_extent_mapping(em_tree, em, 0); 9893ead46bSDavid Sterba write_unlock(&em_tree->lock); 99d7de4b08SDavid Sterba if (ret < 0) { 100d7de4b08SDavid Sterba test_err("cannot add extent range [16K, 20K)"); 101d7de4b08SDavid Sterba goto out; 102d7de4b08SDavid Sterba } 10372b28077SLiu Bo free_extent_map(em); 10472b28077SLiu Bo 10572b28077SLiu Bo em = alloc_extent_map(); 106488f6730SDavid Sterba if (!em) { 1076c304746SDavid Sterba test_std_err(TEST_ALLOC_EXTENT_MAP); 108488f6730SDavid Sterba ret = -ENOMEM; 10972b28077SLiu Bo goto out; 110488f6730SDavid Sterba } 11172b28077SLiu Bo 11272b28077SLiu Bo /* Add [0, 8K), should return [0, 16K) instead. */ 11372b28077SLiu Bo em->start = start; 11472b28077SLiu Bo em->len = len; 11572b28077SLiu Bo em->block_start = start; 11672b28077SLiu Bo em->block_len = len; 11793ead46bSDavid Sterba write_lock(&em_tree->lock); 118f46b24c9SDavid Sterba ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, em->start, em->len); 11993ead46bSDavid Sterba write_unlock(&em_tree->lock); 120d7de4b08SDavid Sterba if (ret) { 1213c7251f2SDavid Sterba test_err("case1 [%llu %llu]: ret %d", start, start + len, ret); 122d7de4b08SDavid Sterba goto out; 123d7de4b08SDavid Sterba } 12472b28077SLiu Bo if (em && 12572b28077SLiu Bo (em->start != 0 || extent_map_end(em) != SZ_16K || 126d7de4b08SDavid Sterba em->block_start != 0 || em->block_len != SZ_16K)) { 1273c7251f2SDavid Sterba test_err( 1283c7251f2SDavid Sterba "case1 [%llu %llu]: ret %d return a wrong em (start %llu len %llu block_start %llu block_len %llu", 12972b28077SLiu Bo start, start + len, ret, em->start, em->len, 13072b28077SLiu Bo em->block_start, em->block_len); 131d7de4b08SDavid Sterba ret = -EINVAL; 132d7de4b08SDavid Sterba } 13372b28077SLiu Bo free_extent_map(em); 13472b28077SLiu Bo out: 13572b28077SLiu Bo free_extent_map_tree(em_tree); 136488f6730SDavid Sterba 137488f6730SDavid Sterba return ret; 13872b28077SLiu Bo } 13972b28077SLiu Bo 14072b28077SLiu Bo /* 14172b28077SLiu Bo * Test scenario: 14272b28077SLiu Bo * 14372b28077SLiu Bo * Reading the inline ending up with EEXIST, ie. read an inline 14472b28077SLiu Bo * extent and discard page cache and read it again. 14572b28077SLiu Bo */ 146488f6730SDavid Sterba static int test_case_2(struct btrfs_fs_info *fs_info, 1470e08eb9bSDavid Sterba struct extent_map_tree *em_tree) 14872b28077SLiu Bo { 14972b28077SLiu Bo struct extent_map *em; 15072b28077SLiu Bo int ret; 15172b28077SLiu Bo 15272b28077SLiu Bo em = alloc_extent_map(); 1536c304746SDavid Sterba if (!em) { 1546c304746SDavid Sterba test_std_err(TEST_ALLOC_EXTENT_MAP); 155488f6730SDavid Sterba return -ENOMEM; 1566c304746SDavid Sterba } 15772b28077SLiu Bo 15872b28077SLiu Bo /* Add [0, 1K) */ 15972b28077SLiu Bo em->start = 0; 16072b28077SLiu Bo em->len = SZ_1K; 16172b28077SLiu Bo em->block_start = EXTENT_MAP_INLINE; 16272b28077SLiu Bo em->block_len = (u64)-1; 16393ead46bSDavid Sterba write_lock(&em_tree->lock); 16472b28077SLiu Bo ret = add_extent_mapping(em_tree, em, 0); 16593ead46bSDavid Sterba write_unlock(&em_tree->lock); 166e71f2e17SDavid Sterba if (ret < 0) { 167e71f2e17SDavid Sterba test_err("cannot add extent range [0, 1K)"); 168e71f2e17SDavid Sterba goto out; 169e71f2e17SDavid Sterba } 17072b28077SLiu Bo free_extent_map(em); 17172b28077SLiu Bo 1723173fd92SDavid Sterba /* Add [4K, 8K) following [0, 1K) */ 17372b28077SLiu Bo em = alloc_extent_map(); 174488f6730SDavid Sterba if (!em) { 1756c304746SDavid Sterba test_std_err(TEST_ALLOC_EXTENT_MAP); 176488f6730SDavid Sterba ret = -ENOMEM; 17772b28077SLiu Bo goto out; 178488f6730SDavid Sterba } 17972b28077SLiu Bo 18072b28077SLiu Bo em->start = SZ_4K; 18172b28077SLiu Bo em->len = SZ_4K; 18272b28077SLiu Bo em->block_start = SZ_4K; 18372b28077SLiu Bo em->block_len = SZ_4K; 18493ead46bSDavid Sterba write_lock(&em_tree->lock); 18572b28077SLiu Bo ret = add_extent_mapping(em_tree, em, 0); 18693ead46bSDavid Sterba write_unlock(&em_tree->lock); 187e71f2e17SDavid Sterba if (ret < 0) { 188e71f2e17SDavid Sterba test_err("cannot add extent range [4K, 8K)"); 189e71f2e17SDavid Sterba goto out; 190e71f2e17SDavid Sterba } 19172b28077SLiu Bo free_extent_map(em); 19272b28077SLiu Bo 19372b28077SLiu Bo em = alloc_extent_map(); 194488f6730SDavid Sterba if (!em) { 1956c304746SDavid Sterba test_std_err(TEST_ALLOC_EXTENT_MAP); 196488f6730SDavid Sterba ret = -ENOMEM; 19772b28077SLiu Bo goto out; 198488f6730SDavid Sterba } 19972b28077SLiu Bo 20072b28077SLiu Bo /* Add [0, 1K) */ 20172b28077SLiu Bo em->start = 0; 20272b28077SLiu Bo em->len = SZ_1K; 20372b28077SLiu Bo em->block_start = EXTENT_MAP_INLINE; 20472b28077SLiu Bo em->block_len = (u64)-1; 20593ead46bSDavid Sterba write_lock(&em_tree->lock); 206f46b24c9SDavid Sterba ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, em->start, em->len); 20793ead46bSDavid Sterba write_unlock(&em_tree->lock); 208e71f2e17SDavid Sterba if (ret) { 2093c7251f2SDavid Sterba test_err("case2 [0 1K]: ret %d", ret); 210e71f2e17SDavid Sterba goto out; 211e71f2e17SDavid Sterba } 21272b28077SLiu Bo if (em && 21372b28077SLiu Bo (em->start != 0 || extent_map_end(em) != SZ_1K || 214e71f2e17SDavid Sterba em->block_start != EXTENT_MAP_INLINE || em->block_len != (u64)-1)) { 2153c7251f2SDavid Sterba test_err( 2163c7251f2SDavid Sterba "case2 [0 1K]: ret %d return a wrong em (start %llu len %llu block_start %llu block_len %llu", 21772b28077SLiu Bo ret, em->start, em->len, em->block_start, 21872b28077SLiu Bo em->block_len); 219e71f2e17SDavid Sterba ret = -EINVAL; 220e71f2e17SDavid Sterba } 22172b28077SLiu Bo free_extent_map(em); 22272b28077SLiu Bo out: 22372b28077SLiu Bo free_extent_map_tree(em_tree); 224488f6730SDavid Sterba 225488f6730SDavid Sterba return ret; 22672b28077SLiu Bo } 22772b28077SLiu Bo 228488f6730SDavid Sterba static int __test_case_3(struct btrfs_fs_info *fs_info, 2290e08eb9bSDavid Sterba struct extent_map_tree *em_tree, u64 start) 230fd87526fSLiu Bo { 231fd87526fSLiu Bo struct extent_map *em; 232fd87526fSLiu Bo u64 len = SZ_4K; 233fd87526fSLiu Bo int ret; 234fd87526fSLiu Bo 235fd87526fSLiu Bo em = alloc_extent_map(); 2366c304746SDavid Sterba if (!em) { 2376c304746SDavid Sterba test_std_err(TEST_ALLOC_EXTENT_MAP); 238488f6730SDavid Sterba return -ENOMEM; 2396c304746SDavid Sterba } 240fd87526fSLiu Bo 241fd87526fSLiu Bo /* Add [4K, 8K) */ 242fd87526fSLiu Bo em->start = SZ_4K; 243fd87526fSLiu Bo em->len = SZ_4K; 244fd87526fSLiu Bo em->block_start = SZ_4K; 245fd87526fSLiu Bo em->block_len = SZ_4K; 24693ead46bSDavid Sterba write_lock(&em_tree->lock); 247fd87526fSLiu Bo ret = add_extent_mapping(em_tree, em, 0); 24893ead46bSDavid Sterba write_unlock(&em_tree->lock); 249992dce74SDavid Sterba if (ret < 0) { 250992dce74SDavid Sterba test_err("cannot add extent range [4K, 8K)"); 251992dce74SDavid Sterba goto out; 252992dce74SDavid Sterba } 253fd87526fSLiu Bo free_extent_map(em); 254fd87526fSLiu Bo 255fd87526fSLiu Bo em = alloc_extent_map(); 256488f6730SDavid Sterba if (!em) { 2576c304746SDavid Sterba test_std_err(TEST_ALLOC_EXTENT_MAP); 258488f6730SDavid Sterba ret = -ENOMEM; 259fd87526fSLiu Bo goto out; 260488f6730SDavid Sterba } 261fd87526fSLiu Bo 262fd87526fSLiu Bo /* Add [0, 16K) */ 263fd87526fSLiu Bo em->start = 0; 264fd87526fSLiu Bo em->len = SZ_16K; 265fd87526fSLiu Bo em->block_start = 0; 266fd87526fSLiu Bo em->block_len = SZ_16K; 26793ead46bSDavid Sterba write_lock(&em_tree->lock); 268f46b24c9SDavid Sterba ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, start, len); 26993ead46bSDavid Sterba write_unlock(&em_tree->lock); 270992dce74SDavid Sterba if (ret) { 2713c7251f2SDavid Sterba test_err("case3 [0x%llx 0x%llx): ret %d", 272fd87526fSLiu Bo start, start + len, ret); 273992dce74SDavid Sterba goto out; 274992dce74SDavid Sterba } 275fd87526fSLiu Bo /* 276fd87526fSLiu Bo * Since bytes within em are contiguous, em->block_start is identical to 277fd87526fSLiu Bo * em->start. 278fd87526fSLiu Bo */ 279fd87526fSLiu Bo if (em && 280fd87526fSLiu Bo (start < em->start || start + len > extent_map_end(em) || 281992dce74SDavid Sterba em->start != em->block_start || em->len != em->block_len)) { 2823c7251f2SDavid Sterba test_err( 2833c7251f2SDavid Sterba "case3 [0x%llx 0x%llx): ret %d em (start 0x%llx len 0x%llx block_start 0x%llx block_len 0x%llx)", 284fd87526fSLiu Bo start, start + len, ret, em->start, em->len, 285fd87526fSLiu Bo em->block_start, em->block_len); 286992dce74SDavid Sterba ret = -EINVAL; 287992dce74SDavid Sterba } 288fd87526fSLiu Bo free_extent_map(em); 289fd87526fSLiu Bo out: 290fd87526fSLiu Bo free_extent_map_tree(em_tree); 291488f6730SDavid Sterba 292488f6730SDavid Sterba return ret; 293fd87526fSLiu Bo } 294fd87526fSLiu Bo 295fd87526fSLiu Bo /* 296fd87526fSLiu Bo * Test scenario: 297fd87526fSLiu Bo * 298fd87526fSLiu Bo * Suppose that no extent map has been loaded into memory yet. 299fd87526fSLiu Bo * There is a file extent [0, 16K), two jobs are running concurrently 300fd87526fSLiu Bo * against it, t1 is buffered writing to [4K, 8K) and t2 is doing dio 301fd87526fSLiu Bo * read from [0, 4K) or [8K, 12K) or [12K, 16K). 302fd87526fSLiu Bo * 303fd87526fSLiu Bo * t1 goes ahead of t2 and adds em [4K, 8K) into tree. 304fd87526fSLiu Bo * 305fd87526fSLiu Bo * t1 t2 306fd87526fSLiu Bo * cow_file_range() btrfs_get_extent() 307fd87526fSLiu Bo * -> lookup_extent_mapping() 308fd87526fSLiu Bo * -> add_extent_mapping() 309fd87526fSLiu Bo * -> add_extent_mapping() 310fd87526fSLiu Bo */ 311ccfada1fSDavid Sterba static int test_case_3(struct btrfs_fs_info *fs_info, 3120e08eb9bSDavid Sterba struct extent_map_tree *em_tree) 313fd87526fSLiu Bo { 314ccfada1fSDavid Sterba int ret; 315ccfada1fSDavid Sterba 316ccfada1fSDavid Sterba ret = __test_case_3(fs_info, em_tree, 0); 317ccfada1fSDavid Sterba if (ret) 318ccfada1fSDavid Sterba return ret; 319ccfada1fSDavid Sterba ret = __test_case_3(fs_info, em_tree, SZ_8K); 320ccfada1fSDavid Sterba if (ret) 321ccfada1fSDavid Sterba return ret; 32243f7cddcSDavid Sterba ret = __test_case_3(fs_info, em_tree, (12 * SZ_1K)); 323ccfada1fSDavid Sterba 324ccfada1fSDavid Sterba return ret; 325fd87526fSLiu Bo } 326fd87526fSLiu Bo 327488f6730SDavid Sterba static int __test_case_4(struct btrfs_fs_info *fs_info, 3280e08eb9bSDavid Sterba struct extent_map_tree *em_tree, u64 start) 329cd77f4f8SLiu Bo { 330cd77f4f8SLiu Bo struct extent_map *em; 331cd77f4f8SLiu Bo u64 len = SZ_4K; 332cd77f4f8SLiu Bo int ret; 333cd77f4f8SLiu Bo 334cd77f4f8SLiu Bo em = alloc_extent_map(); 3356c304746SDavid Sterba if (!em) { 3366c304746SDavid Sterba test_std_err(TEST_ALLOC_EXTENT_MAP); 337488f6730SDavid Sterba return -ENOMEM; 3386c304746SDavid Sterba } 339cd77f4f8SLiu Bo 340cd77f4f8SLiu Bo /* Add [0K, 8K) */ 341cd77f4f8SLiu Bo em->start = 0; 342cd77f4f8SLiu Bo em->len = SZ_8K; 343cd77f4f8SLiu Bo em->block_start = 0; 344cd77f4f8SLiu Bo em->block_len = SZ_8K; 34593ead46bSDavid Sterba write_lock(&em_tree->lock); 346cd77f4f8SLiu Bo ret = add_extent_mapping(em_tree, em, 0); 34793ead46bSDavid Sterba write_unlock(&em_tree->lock); 3487c6f6700SDavid Sterba if (ret < 0) { 3497c6f6700SDavid Sterba test_err("cannot add extent range [0, 8K)"); 3507c6f6700SDavid Sterba goto out; 3517c6f6700SDavid Sterba } 352cd77f4f8SLiu Bo free_extent_map(em); 353cd77f4f8SLiu Bo 354cd77f4f8SLiu Bo em = alloc_extent_map(); 355488f6730SDavid Sterba if (!em) { 3566c304746SDavid Sterba test_std_err(TEST_ALLOC_EXTENT_MAP); 357488f6730SDavid Sterba ret = -ENOMEM; 358cd77f4f8SLiu Bo goto out; 359488f6730SDavid Sterba } 360cd77f4f8SLiu Bo 3613173fd92SDavid Sterba /* Add [8K, 32K) */ 362cd77f4f8SLiu Bo em->start = SZ_8K; 36343f7cddcSDavid Sterba em->len = 24 * SZ_1K; 364cd77f4f8SLiu Bo em->block_start = SZ_16K; /* avoid merging */ 36543f7cddcSDavid Sterba em->block_len = 24 * SZ_1K; 36693ead46bSDavid Sterba write_lock(&em_tree->lock); 367cd77f4f8SLiu Bo ret = add_extent_mapping(em_tree, em, 0); 36893ead46bSDavid Sterba write_unlock(&em_tree->lock); 3697c6f6700SDavid Sterba if (ret < 0) { 3707c6f6700SDavid Sterba test_err("cannot add extent range [8K, 32K)"); 3717c6f6700SDavid Sterba goto out; 3727c6f6700SDavid Sterba } 373cd77f4f8SLiu Bo free_extent_map(em); 374cd77f4f8SLiu Bo 375cd77f4f8SLiu Bo em = alloc_extent_map(); 376488f6730SDavid Sterba if (!em) { 3776c304746SDavid Sterba test_std_err(TEST_ALLOC_EXTENT_MAP); 378488f6730SDavid Sterba ret = -ENOMEM; 379cd77f4f8SLiu Bo goto out; 380488f6730SDavid Sterba } 381cd77f4f8SLiu Bo /* Add [0K, 32K) */ 382cd77f4f8SLiu Bo em->start = 0; 383cd77f4f8SLiu Bo em->len = SZ_32K; 384cd77f4f8SLiu Bo em->block_start = 0; 385cd77f4f8SLiu Bo em->block_len = SZ_32K; 38693ead46bSDavid Sterba write_lock(&em_tree->lock); 387f46b24c9SDavid Sterba ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, start, len); 38893ead46bSDavid Sterba write_unlock(&em_tree->lock); 3897c6f6700SDavid Sterba if (ret) { 3903c7251f2SDavid Sterba test_err("case4 [0x%llx 0x%llx): ret %d", 391cd77f4f8SLiu Bo start, len, ret); 3927c6f6700SDavid Sterba goto out; 3937c6f6700SDavid Sterba } 3947c6f6700SDavid Sterba if (em && (start < em->start || start + len > extent_map_end(em))) { 3953c7251f2SDavid Sterba test_err( 3963c7251f2SDavid Sterba "case4 [0x%llx 0x%llx): ret %d, added wrong em (start 0x%llx len 0x%llx block_start 0x%llx block_len 0x%llx)", 397cd77f4f8SLiu Bo start, len, ret, em->start, em->len, em->block_start, 398cd77f4f8SLiu Bo em->block_len); 3997c6f6700SDavid Sterba ret = -EINVAL; 4007c6f6700SDavid Sterba } 401cd77f4f8SLiu Bo free_extent_map(em); 402cd77f4f8SLiu Bo out: 403cd77f4f8SLiu Bo free_extent_map_tree(em_tree); 404488f6730SDavid Sterba 405488f6730SDavid Sterba return ret; 406cd77f4f8SLiu Bo } 407cd77f4f8SLiu Bo 408cd77f4f8SLiu Bo /* 409cd77f4f8SLiu Bo * Test scenario: 410cd77f4f8SLiu Bo * 411cd77f4f8SLiu Bo * Suppose that no extent map has been loaded into memory yet. 412cd77f4f8SLiu Bo * There is a file extent [0, 32K), two jobs are running concurrently 413cd77f4f8SLiu Bo * against it, t1 is doing dio write to [8K, 32K) and t2 is doing dio 414cd77f4f8SLiu Bo * read from [0, 4K) or [4K, 8K). 415cd77f4f8SLiu Bo * 416cd77f4f8SLiu Bo * t1 goes ahead of t2 and splits em [0, 32K) to em [0K, 8K) and [8K 32K). 417cd77f4f8SLiu Bo * 418cd77f4f8SLiu Bo * t1 t2 419cd77f4f8SLiu Bo * btrfs_get_blocks_direct() btrfs_get_blocks_direct() 420cd77f4f8SLiu Bo * -> btrfs_get_extent() -> btrfs_get_extent() 421cd77f4f8SLiu Bo * -> lookup_extent_mapping() 422cd77f4f8SLiu Bo * -> add_extent_mapping() -> lookup_extent_mapping() 423cd77f4f8SLiu Bo * # load [0, 32K) 424cd77f4f8SLiu Bo * -> btrfs_new_extent_direct() 425cd77f4f8SLiu Bo * -> btrfs_drop_extent_cache() 426cd77f4f8SLiu Bo * # split [0, 32K) 427cd77f4f8SLiu Bo * -> add_extent_mapping() 428cd77f4f8SLiu Bo * # add [8K, 32K) 429cd77f4f8SLiu Bo * -> add_extent_mapping() 430cd77f4f8SLiu Bo * # handle -EEXIST when adding 431cd77f4f8SLiu Bo * # [0, 32K) 432cd77f4f8SLiu Bo */ 433ccfada1fSDavid Sterba static int test_case_4(struct btrfs_fs_info *fs_info, 4340e08eb9bSDavid Sterba struct extent_map_tree *em_tree) 435cd77f4f8SLiu Bo { 436ccfada1fSDavid Sterba int ret; 437ccfada1fSDavid Sterba 438ccfada1fSDavid Sterba ret = __test_case_4(fs_info, em_tree, 0); 439ccfada1fSDavid Sterba if (ret) 440ccfada1fSDavid Sterba return ret; 441ccfada1fSDavid Sterba ret = __test_case_4(fs_info, em_tree, SZ_4K); 442ccfada1fSDavid Sterba 443ccfada1fSDavid Sterba return ret; 444cd77f4f8SLiu Bo } 445cd77f4f8SLiu Bo 44689c37604SJosef Bacik static int add_compressed_extent(struct extent_map_tree *em_tree, 44789c37604SJosef Bacik u64 start, u64 len, u64 block_start) 44889c37604SJosef Bacik { 44989c37604SJosef Bacik struct extent_map *em; 45089c37604SJosef Bacik int ret; 45189c37604SJosef Bacik 45289c37604SJosef Bacik em = alloc_extent_map(); 45389c37604SJosef Bacik if (!em) { 45489c37604SJosef Bacik test_std_err(TEST_ALLOC_EXTENT_MAP); 45589c37604SJosef Bacik return -ENOMEM; 45689c37604SJosef Bacik } 45789c37604SJosef Bacik 45889c37604SJosef Bacik em->start = start; 45989c37604SJosef Bacik em->len = len; 46089c37604SJosef Bacik em->block_start = block_start; 46189c37604SJosef Bacik em->block_len = SZ_4K; 46289c37604SJosef Bacik set_bit(EXTENT_FLAG_COMPRESSED, &em->flags); 46389c37604SJosef Bacik write_lock(&em_tree->lock); 46489c37604SJosef Bacik ret = add_extent_mapping(em_tree, em, 0); 46589c37604SJosef Bacik write_unlock(&em_tree->lock); 46689c37604SJosef Bacik free_extent_map(em); 46789c37604SJosef Bacik if (ret < 0) { 46889c37604SJosef Bacik test_err("cannot add extent map [%llu, %llu)", start, start + len); 46989c37604SJosef Bacik return ret; 47089c37604SJosef Bacik } 47189c37604SJosef Bacik 47289c37604SJosef Bacik return 0; 47389c37604SJosef Bacik } 47489c37604SJosef Bacik 47589c37604SJosef Bacik struct extent_range { 47689c37604SJosef Bacik u64 start; 47789c37604SJosef Bacik u64 len; 47889c37604SJosef Bacik }; 47989c37604SJosef Bacik 48089c37604SJosef Bacik /* The valid states of the tree after every drop, as described below. */ 48189c37604SJosef Bacik struct extent_range valid_ranges[][7] = { 48289c37604SJosef Bacik { 48389c37604SJosef Bacik { .start = 0, .len = SZ_8K }, /* [0, 8K) */ 48489c37604SJosef Bacik { .start = SZ_4K * 3, .len = SZ_4K * 3}, /* [12k, 24k) */ 48589c37604SJosef Bacik { .start = SZ_4K * 6, .len = SZ_4K * 3}, /* [24k, 36k) */ 48689c37604SJosef Bacik { .start = SZ_32K + SZ_4K, .len = SZ_4K}, /* [36k, 40k) */ 48789c37604SJosef Bacik { .start = SZ_4K * 10, .len = SZ_4K * 6}, /* [40k, 64k) */ 48889c37604SJosef Bacik }, 48989c37604SJosef Bacik { 49089c37604SJosef Bacik { .start = 0, .len = SZ_8K }, /* [0, 8K) */ 49189c37604SJosef Bacik { .start = SZ_4K * 5, .len = SZ_4K}, /* [20k, 24k) */ 49289c37604SJosef Bacik { .start = SZ_4K * 6, .len = SZ_4K * 3}, /* [24k, 36k) */ 49389c37604SJosef Bacik { .start = SZ_32K + SZ_4K, .len = SZ_4K}, /* [36k, 40k) */ 49489c37604SJosef Bacik { .start = SZ_4K * 10, .len = SZ_4K * 6}, /* [40k, 64k) */ 49589c37604SJosef Bacik }, 49689c37604SJosef Bacik { 49789c37604SJosef Bacik { .start = 0, .len = SZ_8K }, /* [0, 8K) */ 49889c37604SJosef Bacik { .start = SZ_4K * 5, .len = SZ_4K}, /* [20k, 24k) */ 49989c37604SJosef Bacik { .start = SZ_4K * 6, .len = SZ_4K}, /* [24k, 28k) */ 50089c37604SJosef Bacik { .start = SZ_32K, .len = SZ_4K}, /* [32k, 36k) */ 50189c37604SJosef Bacik { .start = SZ_32K + SZ_4K, .len = SZ_4K}, /* [36k, 40k) */ 50289c37604SJosef Bacik { .start = SZ_4K * 10, .len = SZ_4K * 6}, /* [40k, 64k) */ 50389c37604SJosef Bacik }, 50489c37604SJosef Bacik { 50589c37604SJosef Bacik { .start = 0, .len = SZ_8K}, /* [0, 8K) */ 50689c37604SJosef Bacik { .start = SZ_4K * 5, .len = SZ_4K}, /* [20k, 24k) */ 50789c37604SJosef Bacik { .start = SZ_4K * 6, .len = SZ_4K}, /* [24k, 28k) */ 50889c37604SJosef Bacik } 50989c37604SJosef Bacik }; 51089c37604SJosef Bacik 51189c37604SJosef Bacik static int validate_range(struct extent_map_tree *em_tree, int index) 51289c37604SJosef Bacik { 51389c37604SJosef Bacik struct rb_node *n; 51489c37604SJosef Bacik int i; 51589c37604SJosef Bacik 51689c37604SJosef Bacik for (i = 0, n = rb_first_cached(&em_tree->map); 51789c37604SJosef Bacik valid_ranges[index][i].len && n; 51889c37604SJosef Bacik i++, n = rb_next(n)) { 51989c37604SJosef Bacik struct extent_map *entry = rb_entry(n, struct extent_map, rb_node); 52089c37604SJosef Bacik 52189c37604SJosef Bacik if (entry->start != valid_ranges[index][i].start) { 52289c37604SJosef Bacik test_err("mapping has start %llu expected %llu", 52389c37604SJosef Bacik entry->start, valid_ranges[index][i].start); 52489c37604SJosef Bacik return -EINVAL; 52589c37604SJosef Bacik } 52689c37604SJosef Bacik 52789c37604SJosef Bacik if (entry->len != valid_ranges[index][i].len) { 52889c37604SJosef Bacik test_err("mapping has len %llu expected %llu", 52989c37604SJosef Bacik entry->len, valid_ranges[index][i].len); 53089c37604SJosef Bacik return -EINVAL; 53189c37604SJosef Bacik } 53289c37604SJosef Bacik } 53389c37604SJosef Bacik 53489c37604SJosef Bacik /* 53589c37604SJosef Bacik * We exited because we don't have any more entries in the extent_map 53689c37604SJosef Bacik * but we still expect more valid entries. 53789c37604SJosef Bacik */ 53889c37604SJosef Bacik if (valid_ranges[index][i].len) { 53989c37604SJosef Bacik test_err("missing an entry"); 54089c37604SJosef Bacik return -EINVAL; 54189c37604SJosef Bacik } 54289c37604SJosef Bacik 54389c37604SJosef Bacik /* We exited the loop but still have entries in the extent map. */ 54489c37604SJosef Bacik if (n) { 54589c37604SJosef Bacik test_err("we have a left over entry in the extent map we didn't expect"); 54689c37604SJosef Bacik return -EINVAL; 54789c37604SJosef Bacik } 54889c37604SJosef Bacik 54989c37604SJosef Bacik return 0; 55089c37604SJosef Bacik } 55189c37604SJosef Bacik 55289c37604SJosef Bacik /* 55389c37604SJosef Bacik * Test scenario: 55489c37604SJosef Bacik * 55589c37604SJosef Bacik * Test the various edge cases of btrfs_drop_extent_map_range, create the 55689c37604SJosef Bacik * following ranges 55789c37604SJosef Bacik * 55889c37604SJosef Bacik * [0, 12k)[12k, 24k)[24k, 36k)[36k, 40k)[40k,64k) 55989c37604SJosef Bacik * 56089c37604SJosef Bacik * And then we'll drop: 56189c37604SJosef Bacik * 56289c37604SJosef Bacik * [8k, 12k) - test the single front split 56389c37604SJosef Bacik * [12k, 20k) - test the single back split 56489c37604SJosef Bacik * [28k, 32k) - test the double split 56589c37604SJosef Bacik * [32k, 64k) - test whole em dropping 56689c37604SJosef Bacik * 56789c37604SJosef Bacik * They'll have the EXTENT_FLAG_COMPRESSED flag set to keep the em tree from 56889c37604SJosef Bacik * merging the em's. 56989c37604SJosef Bacik */ 57089c37604SJosef Bacik static int test_case_5(void) 57189c37604SJosef Bacik { 57289c37604SJosef Bacik struct extent_map_tree *em_tree; 57389c37604SJosef Bacik struct inode *inode; 57489c37604SJosef Bacik u64 start, end; 57589c37604SJosef Bacik int ret; 57689c37604SJosef Bacik 57789c37604SJosef Bacik test_msg("Running btrfs_drop_extent_map_range tests"); 57889c37604SJosef Bacik 57989c37604SJosef Bacik inode = btrfs_new_test_inode(); 58089c37604SJosef Bacik if (!inode) { 58189c37604SJosef Bacik test_std_err(TEST_ALLOC_INODE); 58289c37604SJosef Bacik return -ENOMEM; 58389c37604SJosef Bacik } 58489c37604SJosef Bacik 58589c37604SJosef Bacik em_tree = &BTRFS_I(inode)->extent_tree; 58689c37604SJosef Bacik 58789c37604SJosef Bacik /* [0, 12k) */ 58889c37604SJosef Bacik ret = add_compressed_extent(em_tree, 0, SZ_4K * 3, 0); 58989c37604SJosef Bacik if (ret) { 59089c37604SJosef Bacik test_err("cannot add extent range [0, 12K)"); 59189c37604SJosef Bacik goto out; 59289c37604SJosef Bacik } 59389c37604SJosef Bacik 59489c37604SJosef Bacik /* [12k, 24k) */ 59589c37604SJosef Bacik ret = add_compressed_extent(em_tree, SZ_4K * 3, SZ_4K * 3, SZ_4K); 59689c37604SJosef Bacik if (ret) { 59789c37604SJosef Bacik test_err("cannot add extent range [12k, 24k)"); 59889c37604SJosef Bacik goto out; 59989c37604SJosef Bacik } 60089c37604SJosef Bacik 60189c37604SJosef Bacik /* [24k, 36k) */ 60289c37604SJosef Bacik ret = add_compressed_extent(em_tree, SZ_4K * 6, SZ_4K * 3, SZ_8K); 60389c37604SJosef Bacik if (ret) { 60489c37604SJosef Bacik test_err("cannot add extent range [12k, 24k)"); 60589c37604SJosef Bacik goto out; 60689c37604SJosef Bacik } 60789c37604SJosef Bacik 60889c37604SJosef Bacik /* [36k, 40k) */ 60989c37604SJosef Bacik ret = add_compressed_extent(em_tree, SZ_32K + SZ_4K, SZ_4K, SZ_4K * 3); 61089c37604SJosef Bacik if (ret) { 61189c37604SJosef Bacik test_err("cannot add extent range [12k, 24k)"); 61289c37604SJosef Bacik goto out; 61389c37604SJosef Bacik } 61489c37604SJosef Bacik 61589c37604SJosef Bacik /* [40k, 64k) */ 61689c37604SJosef Bacik ret = add_compressed_extent(em_tree, SZ_4K * 10, SZ_4K * 6, SZ_16K); 61789c37604SJosef Bacik if (ret) { 61889c37604SJosef Bacik test_err("cannot add extent range [12k, 24k)"); 61989c37604SJosef Bacik goto out; 62089c37604SJosef Bacik } 62189c37604SJosef Bacik 62289c37604SJosef Bacik /* Drop [8k, 12k) */ 62389c37604SJosef Bacik start = SZ_8K; 62489c37604SJosef Bacik end = (3 * SZ_4K) - 1; 62589c37604SJosef Bacik btrfs_drop_extent_map_range(BTRFS_I(inode), start, end, false); 62689c37604SJosef Bacik ret = validate_range(&BTRFS_I(inode)->extent_tree, 0); 62789c37604SJosef Bacik if (ret) 62889c37604SJosef Bacik goto out; 62989c37604SJosef Bacik 63089c37604SJosef Bacik /* Drop [12k, 20k) */ 63189c37604SJosef Bacik start = SZ_4K * 3; 63289c37604SJosef Bacik end = SZ_16K + SZ_4K - 1; 63389c37604SJosef Bacik btrfs_drop_extent_map_range(BTRFS_I(inode), start, end, false); 63489c37604SJosef Bacik ret = validate_range(&BTRFS_I(inode)->extent_tree, 1); 63589c37604SJosef Bacik if (ret) 63689c37604SJosef Bacik goto out; 63789c37604SJosef Bacik 63889c37604SJosef Bacik /* Drop [28k, 32k) */ 63989c37604SJosef Bacik start = SZ_32K - SZ_4K; 64089c37604SJosef Bacik end = SZ_32K - 1; 64189c37604SJosef Bacik btrfs_drop_extent_map_range(BTRFS_I(inode), start, end, false); 64289c37604SJosef Bacik ret = validate_range(&BTRFS_I(inode)->extent_tree, 2); 64389c37604SJosef Bacik if (ret) 64489c37604SJosef Bacik goto out; 64589c37604SJosef Bacik 64689c37604SJosef Bacik /* Drop [32k, 64k) */ 64789c37604SJosef Bacik start = SZ_32K; 64889c37604SJosef Bacik end = SZ_64K - 1; 64989c37604SJosef Bacik btrfs_drop_extent_map_range(BTRFS_I(inode), start, end, false); 65089c37604SJosef Bacik ret = validate_range(&BTRFS_I(inode)->extent_tree, 3); 65189c37604SJosef Bacik if (ret) 65289c37604SJosef Bacik goto out; 65389c37604SJosef Bacik out: 65489c37604SJosef Bacik iput(inode); 65589c37604SJosef Bacik return ret; 65689c37604SJosef Bacik } 65789c37604SJosef Bacik 658*f345dbdfSJosef Bacik /* 659*f345dbdfSJosef Bacik * Test the btrfs_add_extent_mapping helper which will attempt to create an em 660*f345dbdfSJosef Bacik * for areas between two existing ems. Validate it doesn't do this when there 661*f345dbdfSJosef Bacik * are two unmerged em's side by side. 662*f345dbdfSJosef Bacik */ 663*f345dbdfSJosef Bacik static int test_case_6(struct btrfs_fs_info *fs_info, struct extent_map_tree *em_tree) 664*f345dbdfSJosef Bacik { 665*f345dbdfSJosef Bacik struct extent_map *em = NULL; 666*f345dbdfSJosef Bacik int ret; 667*f345dbdfSJosef Bacik 668*f345dbdfSJosef Bacik ret = add_compressed_extent(em_tree, 0, SZ_4K, 0); 669*f345dbdfSJosef Bacik if (ret) 670*f345dbdfSJosef Bacik goto out; 671*f345dbdfSJosef Bacik 672*f345dbdfSJosef Bacik ret = add_compressed_extent(em_tree, SZ_4K, SZ_4K, 0); 673*f345dbdfSJosef Bacik if (ret) 674*f345dbdfSJosef Bacik goto out; 675*f345dbdfSJosef Bacik 676*f345dbdfSJosef Bacik em = alloc_extent_map(); 677*f345dbdfSJosef Bacik if (!em) { 678*f345dbdfSJosef Bacik test_std_err(TEST_ALLOC_EXTENT_MAP); 679*f345dbdfSJosef Bacik return -ENOMEM; 680*f345dbdfSJosef Bacik } 681*f345dbdfSJosef Bacik 682*f345dbdfSJosef Bacik em->start = SZ_4K; 683*f345dbdfSJosef Bacik em->len = SZ_4K; 684*f345dbdfSJosef Bacik em->block_start = SZ_16K; 685*f345dbdfSJosef Bacik em->block_len = SZ_16K; 686*f345dbdfSJosef Bacik write_lock(&em_tree->lock); 687*f345dbdfSJosef Bacik ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, 0, SZ_8K); 688*f345dbdfSJosef Bacik write_unlock(&em_tree->lock); 689*f345dbdfSJosef Bacik 690*f345dbdfSJosef Bacik if (ret != 0) { 691*f345dbdfSJosef Bacik test_err("got an error when adding our em: %d", ret); 692*f345dbdfSJosef Bacik goto out; 693*f345dbdfSJosef Bacik } 694*f345dbdfSJosef Bacik 695*f345dbdfSJosef Bacik ret = -EINVAL; 696*f345dbdfSJosef Bacik if (em->start != 0) { 697*f345dbdfSJosef Bacik test_err("unexpected em->start at %llu, wanted 0", em->start); 698*f345dbdfSJosef Bacik goto out; 699*f345dbdfSJosef Bacik } 700*f345dbdfSJosef Bacik if (em->len != SZ_4K) { 701*f345dbdfSJosef Bacik test_err("unexpected em->len %llu, expected 4K", em->len); 702*f345dbdfSJosef Bacik goto out; 703*f345dbdfSJosef Bacik } 704*f345dbdfSJosef Bacik ret = 0; 705*f345dbdfSJosef Bacik out: 706*f345dbdfSJosef Bacik free_extent_map(em); 707*f345dbdfSJosef Bacik free_extent_map_tree(em_tree); 708*f345dbdfSJosef Bacik return ret; 709*f345dbdfSJosef Bacik } 710*f345dbdfSJosef Bacik 711bf2e2eb0SNikolay Borisov struct rmap_test_vector { 712bf2e2eb0SNikolay Borisov u64 raid_type; 713bf2e2eb0SNikolay Borisov u64 physical_start; 714bf2e2eb0SNikolay Borisov u64 data_stripe_size; 715bf2e2eb0SNikolay Borisov u64 num_data_stripes; 716bf2e2eb0SNikolay Borisov u64 num_stripes; 717bf2e2eb0SNikolay Borisov /* Assume we won't have more than 5 physical stripes */ 718bf2e2eb0SNikolay Borisov u64 data_stripe_phys_start[5]; 719bf2e2eb0SNikolay Borisov bool expected_mapped_addr; 720bf2e2eb0SNikolay Borisov /* Physical to logical addresses */ 721bf2e2eb0SNikolay Borisov u64 mapped_logical[5]; 722bf2e2eb0SNikolay Borisov }; 723bf2e2eb0SNikolay Borisov 724bf2e2eb0SNikolay Borisov static int test_rmap_block(struct btrfs_fs_info *fs_info, 725bf2e2eb0SNikolay Borisov struct rmap_test_vector *test) 726bf2e2eb0SNikolay Borisov { 727bf2e2eb0SNikolay Borisov struct extent_map *em; 728bf2e2eb0SNikolay Borisov struct map_lookup *map = NULL; 729bf2e2eb0SNikolay Borisov u64 *logical = NULL; 730bf2e2eb0SNikolay Borisov int i, out_ndaddrs, out_stripe_len; 731bf2e2eb0SNikolay Borisov int ret; 732bf2e2eb0SNikolay Borisov 733bf2e2eb0SNikolay Borisov em = alloc_extent_map(); 734bf2e2eb0SNikolay Borisov if (!em) { 735bf2e2eb0SNikolay Borisov test_std_err(TEST_ALLOC_EXTENT_MAP); 736bf2e2eb0SNikolay Borisov return -ENOMEM; 737bf2e2eb0SNikolay Borisov } 738bf2e2eb0SNikolay Borisov 739bf2e2eb0SNikolay Borisov map = kmalloc(map_lookup_size(test->num_stripes), GFP_KERNEL); 740bf2e2eb0SNikolay Borisov if (!map) { 741bf2e2eb0SNikolay Borisov kfree(em); 742bf2e2eb0SNikolay Borisov test_std_err(TEST_ALLOC_EXTENT_MAP); 743bf2e2eb0SNikolay Borisov return -ENOMEM; 744bf2e2eb0SNikolay Borisov } 745bf2e2eb0SNikolay Borisov 746bf2e2eb0SNikolay Borisov set_bit(EXTENT_FLAG_FS_MAPPING, &em->flags); 747bf2e2eb0SNikolay Borisov /* Start at 4GiB logical address */ 748bf2e2eb0SNikolay Borisov em->start = SZ_4G; 749bf2e2eb0SNikolay Borisov em->len = test->data_stripe_size * test->num_data_stripes; 750bf2e2eb0SNikolay Borisov em->block_len = em->len; 751bf2e2eb0SNikolay Borisov em->orig_block_len = test->data_stripe_size; 752bf2e2eb0SNikolay Borisov em->map_lookup = map; 753bf2e2eb0SNikolay Borisov 754bf2e2eb0SNikolay Borisov map->num_stripes = test->num_stripes; 755bf2e2eb0SNikolay Borisov map->type = test->raid_type; 756bf2e2eb0SNikolay Borisov 757bf2e2eb0SNikolay Borisov for (i = 0; i < map->num_stripes; i++) { 758bf2e2eb0SNikolay Borisov struct btrfs_device *dev = btrfs_alloc_dummy_device(fs_info); 759bf2e2eb0SNikolay Borisov 760bf2e2eb0SNikolay Borisov if (IS_ERR(dev)) { 761bf2e2eb0SNikolay Borisov test_err("cannot allocate device"); 762bf2e2eb0SNikolay Borisov ret = PTR_ERR(dev); 763bf2e2eb0SNikolay Borisov goto out; 764bf2e2eb0SNikolay Borisov } 765bf2e2eb0SNikolay Borisov map->stripes[i].dev = dev; 766bf2e2eb0SNikolay Borisov map->stripes[i].physical = test->data_stripe_phys_start[i]; 767bf2e2eb0SNikolay Borisov } 768bf2e2eb0SNikolay Borisov 769bf2e2eb0SNikolay Borisov write_lock(&fs_info->mapping_tree.lock); 770bf2e2eb0SNikolay Borisov ret = add_extent_mapping(&fs_info->mapping_tree, em, 0); 771bf2e2eb0SNikolay Borisov write_unlock(&fs_info->mapping_tree.lock); 772bf2e2eb0SNikolay Borisov if (ret) { 773bf2e2eb0SNikolay Borisov test_err("error adding block group mapping to mapping tree"); 774bf2e2eb0SNikolay Borisov goto out_free; 775bf2e2eb0SNikolay Borisov } 776bf2e2eb0SNikolay Borisov 7771eb82ef8SChristoph Hellwig ret = btrfs_rmap_block(fs_info, em->start, btrfs_sb_offset(1), 778bf2e2eb0SNikolay Borisov &logical, &out_ndaddrs, &out_stripe_len); 779bf2e2eb0SNikolay Borisov if (ret || (out_ndaddrs == 0 && test->expected_mapped_addr)) { 780bf2e2eb0SNikolay Borisov test_err("didn't rmap anything but expected %d", 781bf2e2eb0SNikolay Borisov test->expected_mapped_addr); 782bf2e2eb0SNikolay Borisov goto out; 783bf2e2eb0SNikolay Borisov } 784bf2e2eb0SNikolay Borisov 785bf2e2eb0SNikolay Borisov if (out_stripe_len != BTRFS_STRIPE_LEN) { 786bf2e2eb0SNikolay Borisov test_err("calculated stripe length doesn't match"); 787bf2e2eb0SNikolay Borisov goto out; 788bf2e2eb0SNikolay Borisov } 789bf2e2eb0SNikolay Borisov 790bf2e2eb0SNikolay Borisov if (out_ndaddrs != test->expected_mapped_addr) { 791bf2e2eb0SNikolay Borisov for (i = 0; i < out_ndaddrs; i++) 792bf2e2eb0SNikolay Borisov test_msg("mapped %llu", logical[i]); 793bf2e2eb0SNikolay Borisov test_err("unexpected number of mapped addresses: %d", out_ndaddrs); 794bf2e2eb0SNikolay Borisov goto out; 795bf2e2eb0SNikolay Borisov } 796bf2e2eb0SNikolay Borisov 797bf2e2eb0SNikolay Borisov for (i = 0; i < out_ndaddrs; i++) { 798bf2e2eb0SNikolay Borisov if (logical[i] != test->mapped_logical[i]) { 799bf2e2eb0SNikolay Borisov test_err("unexpected logical address mapped"); 800bf2e2eb0SNikolay Borisov goto out; 801bf2e2eb0SNikolay Borisov } 802bf2e2eb0SNikolay Borisov } 803bf2e2eb0SNikolay Borisov 804bf2e2eb0SNikolay Borisov ret = 0; 805bf2e2eb0SNikolay Borisov out: 806bf2e2eb0SNikolay Borisov write_lock(&fs_info->mapping_tree.lock); 807bf2e2eb0SNikolay Borisov remove_extent_mapping(&fs_info->mapping_tree, em); 808bf2e2eb0SNikolay Borisov write_unlock(&fs_info->mapping_tree.lock); 809bf2e2eb0SNikolay Borisov /* For us */ 810bf2e2eb0SNikolay Borisov free_extent_map(em); 811bf2e2eb0SNikolay Borisov out_free: 812bf2e2eb0SNikolay Borisov /* For the tree */ 813bf2e2eb0SNikolay Borisov free_extent_map(em); 814bf2e2eb0SNikolay Borisov kfree(logical); 815bf2e2eb0SNikolay Borisov return ret; 816bf2e2eb0SNikolay Borisov } 817bf2e2eb0SNikolay Borisov 81897dc231eSColin Ian King int btrfs_test_extent_map(void) 81972b28077SLiu Bo { 8200e08eb9bSDavid Sterba struct btrfs_fs_info *fs_info = NULL; 82172b28077SLiu Bo struct extent_map_tree *em_tree; 822bf2e2eb0SNikolay Borisov int ret = 0, i; 823bf2e2eb0SNikolay Borisov struct rmap_test_vector rmap_tests[] = { 824bf2e2eb0SNikolay Borisov { 825bf2e2eb0SNikolay Borisov /* 826bf2e2eb0SNikolay Borisov * Test a chunk with 2 data stripes one of which 8271a9fd417SDavid Sterba * intersects the physical address of the super block 828bf2e2eb0SNikolay Borisov * is correctly recognised. 829bf2e2eb0SNikolay Borisov */ 830bf2e2eb0SNikolay Borisov .raid_type = BTRFS_BLOCK_GROUP_RAID1, 831bf2e2eb0SNikolay Borisov .physical_start = SZ_64M - SZ_4M, 832bf2e2eb0SNikolay Borisov .data_stripe_size = SZ_256M, 833bf2e2eb0SNikolay Borisov .num_data_stripes = 2, 834bf2e2eb0SNikolay Borisov .num_stripes = 2, 835bf2e2eb0SNikolay Borisov .data_stripe_phys_start = 836bf2e2eb0SNikolay Borisov {SZ_64M - SZ_4M, SZ_64M - SZ_4M + SZ_256M}, 837bf2e2eb0SNikolay Borisov .expected_mapped_addr = true, 838bf2e2eb0SNikolay Borisov .mapped_logical= {SZ_4G + SZ_4M} 839bf2e2eb0SNikolay Borisov }, 840bf2e2eb0SNikolay Borisov { 841bf2e2eb0SNikolay Borisov /* 842bf2e2eb0SNikolay Borisov * Test that out-of-range physical addresses are 843bf2e2eb0SNikolay Borisov * ignored 844bf2e2eb0SNikolay Borisov */ 845bf2e2eb0SNikolay Borisov 846bf2e2eb0SNikolay Borisov /* SINGLE chunk type */ 847bf2e2eb0SNikolay Borisov .raid_type = 0, 848bf2e2eb0SNikolay Borisov .physical_start = SZ_4G, 849bf2e2eb0SNikolay Borisov .data_stripe_size = SZ_256M, 850bf2e2eb0SNikolay Borisov .num_data_stripes = 1, 851bf2e2eb0SNikolay Borisov .num_stripes = 1, 852bf2e2eb0SNikolay Borisov .data_stripe_phys_start = {SZ_256M}, 853bf2e2eb0SNikolay Borisov .expected_mapped_addr = false, 854bf2e2eb0SNikolay Borisov .mapped_logical = {0} 855bf2e2eb0SNikolay Borisov } 856bf2e2eb0SNikolay Borisov }; 85772b28077SLiu Bo 858315b76b4SDavid Sterba test_msg("running extent_map tests"); 85972b28077SLiu Bo 8600e08eb9bSDavid Sterba /* 8610e08eb9bSDavid Sterba * Note: the fs_info is not set up completely, we only need 8620e08eb9bSDavid Sterba * fs_info::fsid for the tracepoint. 8630e08eb9bSDavid Sterba */ 8640e08eb9bSDavid Sterba fs_info = btrfs_alloc_dummy_fs_info(PAGE_SIZE, PAGE_SIZE); 8650e08eb9bSDavid Sterba if (!fs_info) { 86637b2a7bcSDavid Sterba test_std_err(TEST_ALLOC_FS_INFO); 8670e08eb9bSDavid Sterba return -ENOMEM; 8680e08eb9bSDavid Sterba } 8690e08eb9bSDavid Sterba 87072b28077SLiu Bo em_tree = kzalloc(sizeof(*em_tree), GFP_KERNEL); 871488f6730SDavid Sterba if (!em_tree) { 872488f6730SDavid Sterba ret = -ENOMEM; 8730e08eb9bSDavid Sterba goto out; 874488f6730SDavid Sterba } 87572b28077SLiu Bo 87672b28077SLiu Bo extent_map_tree_init(em_tree); 87772b28077SLiu Bo 878ccfada1fSDavid Sterba ret = test_case_1(fs_info, em_tree); 879ccfada1fSDavid Sterba if (ret) 880ccfada1fSDavid Sterba goto out; 881ccfada1fSDavid Sterba ret = test_case_2(fs_info, em_tree); 882ccfada1fSDavid Sterba if (ret) 883ccfada1fSDavid Sterba goto out; 884ccfada1fSDavid Sterba ret = test_case_3(fs_info, em_tree); 885ccfada1fSDavid Sterba if (ret) 886ccfada1fSDavid Sterba goto out; 887ccfada1fSDavid Sterba ret = test_case_4(fs_info, em_tree); 88889c37604SJosef Bacik if (ret) 88989c37604SJosef Bacik goto out; 89089c37604SJosef Bacik ret = test_case_5(); 89189c37604SJosef Bacik if (ret) 89289c37604SJosef Bacik goto out; 893*f345dbdfSJosef Bacik ret = test_case_6(fs_info, em_tree); 894*f345dbdfSJosef Bacik if (ret) 895*f345dbdfSJosef Bacik goto out; 89672b28077SLiu Bo 897bf2e2eb0SNikolay Borisov test_msg("running rmap tests"); 898bf2e2eb0SNikolay Borisov for (i = 0; i < ARRAY_SIZE(rmap_tests); i++) { 899bf2e2eb0SNikolay Borisov ret = test_rmap_block(fs_info, &rmap_tests[i]); 900bf2e2eb0SNikolay Borisov if (ret) 901bf2e2eb0SNikolay Borisov goto out; 902bf2e2eb0SNikolay Borisov } 903bf2e2eb0SNikolay Borisov 9040e08eb9bSDavid Sterba out: 905ccfada1fSDavid Sterba kfree(em_tree); 9060e08eb9bSDavid Sterba btrfs_free_dummy_fs_info(fs_info); 9070e08eb9bSDavid Sterba 908488f6730SDavid Sterba return ret; 90972b28077SLiu Bo } 910