| .. | .. |
|---|
| 6 | 6 | #include <linux/types.h> |
|---|
| 7 | 7 | #include "btrfs-tests.h" |
|---|
| 8 | 8 | #include "../ctree.h" |
|---|
| 9 | +#include "../volumes.h" |
|---|
| 10 | +#include "../disk-io.h" |
|---|
| 11 | +#include "../block-group.h" |
|---|
| 9 | 12 | |
|---|
| 10 | 13 | static void free_extent_map_tree(struct extent_map_tree *em_tree) |
|---|
| 11 | 14 | { |
|---|
| 12 | 15 | struct extent_map *em; |
|---|
| 13 | 16 | struct rb_node *node; |
|---|
| 14 | 17 | |
|---|
| 15 | | - while (!RB_EMPTY_ROOT(&em_tree->map)) { |
|---|
| 16 | | - node = rb_first(&em_tree->map); |
|---|
| 18 | + while (!RB_EMPTY_ROOT(&em_tree->map.rb_root)) { |
|---|
| 19 | + node = rb_first_cached(&em_tree->map); |
|---|
| 17 | 20 | em = rb_entry(node, struct extent_map, rb_node); |
|---|
| 18 | 21 | remove_extent_mapping(em_tree, em); |
|---|
| 19 | 22 | |
|---|
| .. | .. |
|---|
| 47 | 50 | * ->add_extent_mapping(0, 16K) |
|---|
| 48 | 51 | * -> #handle -EEXIST |
|---|
| 49 | 52 | */ |
|---|
| 50 | | -static void test_case_1(struct btrfs_fs_info *fs_info, |
|---|
| 53 | +static int test_case_1(struct btrfs_fs_info *fs_info, |
|---|
| 51 | 54 | struct extent_map_tree *em_tree) |
|---|
| 52 | 55 | { |
|---|
| 53 | 56 | struct extent_map *em; |
|---|
| .. | .. |
|---|
| 56 | 59 | int ret; |
|---|
| 57 | 60 | |
|---|
| 58 | 61 | em = alloc_extent_map(); |
|---|
| 59 | | - if (!em) |
|---|
| 60 | | - /* Skip the test on error. */ |
|---|
| 61 | | - return; |
|---|
| 62 | + if (!em) { |
|---|
| 63 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
|---|
| 64 | + return -ENOMEM; |
|---|
| 65 | + } |
|---|
| 62 | 66 | |
|---|
| 63 | 67 | /* Add [0, 16K) */ |
|---|
| 64 | 68 | em->start = 0; |
|---|
| 65 | 69 | em->len = SZ_16K; |
|---|
| 66 | 70 | em->block_start = 0; |
|---|
| 67 | 71 | em->block_len = SZ_16K; |
|---|
| 72 | + write_lock(&em_tree->lock); |
|---|
| 68 | 73 | ret = add_extent_mapping(em_tree, em, 0); |
|---|
| 69 | | - ASSERT(ret == 0); |
|---|
| 74 | + write_unlock(&em_tree->lock); |
|---|
| 75 | + if (ret < 0) { |
|---|
| 76 | + test_err("cannot add extent range [0, 16K)"); |
|---|
| 77 | + goto out; |
|---|
| 78 | + } |
|---|
| 70 | 79 | free_extent_map(em); |
|---|
| 71 | 80 | |
|---|
| 72 | 81 | /* Add [16K, 20K) following [0, 16K) */ |
|---|
| 73 | 82 | em = alloc_extent_map(); |
|---|
| 74 | | - if (!em) |
|---|
| 83 | + if (!em) { |
|---|
| 84 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
|---|
| 85 | + ret = -ENOMEM; |
|---|
| 75 | 86 | goto out; |
|---|
| 87 | + } |
|---|
| 76 | 88 | |
|---|
| 77 | 89 | em->start = SZ_16K; |
|---|
| 78 | 90 | em->len = SZ_4K; |
|---|
| 79 | 91 | em->block_start = SZ_32K; /* avoid merging */ |
|---|
| 80 | 92 | em->block_len = SZ_4K; |
|---|
| 93 | + write_lock(&em_tree->lock); |
|---|
| 81 | 94 | ret = add_extent_mapping(em_tree, em, 0); |
|---|
| 82 | | - ASSERT(ret == 0); |
|---|
| 95 | + write_unlock(&em_tree->lock); |
|---|
| 96 | + if (ret < 0) { |
|---|
| 97 | + test_err("cannot add extent range [16K, 20K)"); |
|---|
| 98 | + goto out; |
|---|
| 99 | + } |
|---|
| 83 | 100 | free_extent_map(em); |
|---|
| 84 | 101 | |
|---|
| 85 | 102 | em = alloc_extent_map(); |
|---|
| 86 | | - if (!em) |
|---|
| 103 | + if (!em) { |
|---|
| 104 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
|---|
| 105 | + ret = -ENOMEM; |
|---|
| 87 | 106 | goto out; |
|---|
| 107 | + } |
|---|
| 88 | 108 | |
|---|
| 89 | 109 | /* Add [0, 8K), should return [0, 16K) instead. */ |
|---|
| 90 | 110 | em->start = start; |
|---|
| 91 | 111 | em->len = len; |
|---|
| 92 | 112 | em->block_start = start; |
|---|
| 93 | 113 | em->block_len = len; |
|---|
| 114 | + write_lock(&em_tree->lock); |
|---|
| 94 | 115 | ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, em->start, em->len); |
|---|
| 95 | | - if (ret) |
|---|
| 116 | + write_unlock(&em_tree->lock); |
|---|
| 117 | + if (ret) { |
|---|
| 96 | 118 | test_err("case1 [%llu %llu]: ret %d", start, start + len, ret); |
|---|
| 119 | + goto out; |
|---|
| 120 | + } |
|---|
| 97 | 121 | if (em && |
|---|
| 98 | 122 | (em->start != 0 || extent_map_end(em) != SZ_16K || |
|---|
| 99 | | - em->block_start != 0 || em->block_len != SZ_16K)) |
|---|
| 123 | + em->block_start != 0 || em->block_len != SZ_16K)) { |
|---|
| 100 | 124 | test_err( |
|---|
| 101 | 125 | "case1 [%llu %llu]: ret %d return a wrong em (start %llu len %llu block_start %llu block_len %llu", |
|---|
| 102 | 126 | start, start + len, ret, em->start, em->len, |
|---|
| 103 | 127 | em->block_start, em->block_len); |
|---|
| 128 | + ret = -EINVAL; |
|---|
| 129 | + } |
|---|
| 104 | 130 | free_extent_map(em); |
|---|
| 105 | 131 | out: |
|---|
| 106 | | - /* free memory */ |
|---|
| 107 | 132 | free_extent_map_tree(em_tree); |
|---|
| 133 | + |
|---|
| 134 | + return ret; |
|---|
| 108 | 135 | } |
|---|
| 109 | 136 | |
|---|
| 110 | 137 | /* |
|---|
| .. | .. |
|---|
| 113 | 140 | * Reading the inline ending up with EEXIST, ie. read an inline |
|---|
| 114 | 141 | * extent and discard page cache and read it again. |
|---|
| 115 | 142 | */ |
|---|
| 116 | | -static void test_case_2(struct btrfs_fs_info *fs_info, |
|---|
| 143 | +static int test_case_2(struct btrfs_fs_info *fs_info, |
|---|
| 117 | 144 | struct extent_map_tree *em_tree) |
|---|
| 118 | 145 | { |
|---|
| 119 | 146 | struct extent_map *em; |
|---|
| 120 | 147 | int ret; |
|---|
| 121 | 148 | |
|---|
| 122 | 149 | em = alloc_extent_map(); |
|---|
| 123 | | - if (!em) |
|---|
| 124 | | - /* Skip the test on error. */ |
|---|
| 125 | | - return; |
|---|
| 150 | + if (!em) { |
|---|
| 151 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
|---|
| 152 | + return -ENOMEM; |
|---|
| 153 | + } |
|---|
| 126 | 154 | |
|---|
| 127 | 155 | /* Add [0, 1K) */ |
|---|
| 128 | 156 | em->start = 0; |
|---|
| 129 | 157 | em->len = SZ_1K; |
|---|
| 130 | 158 | em->block_start = EXTENT_MAP_INLINE; |
|---|
| 131 | 159 | em->block_len = (u64)-1; |
|---|
| 160 | + write_lock(&em_tree->lock); |
|---|
| 132 | 161 | ret = add_extent_mapping(em_tree, em, 0); |
|---|
| 133 | | - ASSERT(ret == 0); |
|---|
| 162 | + write_unlock(&em_tree->lock); |
|---|
| 163 | + if (ret < 0) { |
|---|
| 164 | + test_err("cannot add extent range [0, 1K)"); |
|---|
| 165 | + goto out; |
|---|
| 166 | + } |
|---|
| 134 | 167 | free_extent_map(em); |
|---|
| 135 | 168 | |
|---|
| 136 | | - /* Add [4K, 4K) following [0, 1K) */ |
|---|
| 169 | + /* Add [4K, 8K) following [0, 1K) */ |
|---|
| 137 | 170 | em = alloc_extent_map(); |
|---|
| 138 | | - if (!em) |
|---|
| 171 | + if (!em) { |
|---|
| 172 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
|---|
| 173 | + ret = -ENOMEM; |
|---|
| 139 | 174 | goto out; |
|---|
| 175 | + } |
|---|
| 140 | 176 | |
|---|
| 141 | 177 | em->start = SZ_4K; |
|---|
| 142 | 178 | em->len = SZ_4K; |
|---|
| 143 | 179 | em->block_start = SZ_4K; |
|---|
| 144 | 180 | em->block_len = SZ_4K; |
|---|
| 181 | + write_lock(&em_tree->lock); |
|---|
| 145 | 182 | ret = add_extent_mapping(em_tree, em, 0); |
|---|
| 146 | | - ASSERT(ret == 0); |
|---|
| 183 | + write_unlock(&em_tree->lock); |
|---|
| 184 | + if (ret < 0) { |
|---|
| 185 | + test_err("cannot add extent range [4K, 8K)"); |
|---|
| 186 | + goto out; |
|---|
| 187 | + } |
|---|
| 147 | 188 | free_extent_map(em); |
|---|
| 148 | 189 | |
|---|
| 149 | 190 | em = alloc_extent_map(); |
|---|
| 150 | | - if (!em) |
|---|
| 191 | + if (!em) { |
|---|
| 192 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
|---|
| 193 | + ret = -ENOMEM; |
|---|
| 151 | 194 | goto out; |
|---|
| 195 | + } |
|---|
| 152 | 196 | |
|---|
| 153 | 197 | /* Add [0, 1K) */ |
|---|
| 154 | 198 | em->start = 0; |
|---|
| 155 | 199 | em->len = SZ_1K; |
|---|
| 156 | 200 | em->block_start = EXTENT_MAP_INLINE; |
|---|
| 157 | 201 | em->block_len = (u64)-1; |
|---|
| 202 | + write_lock(&em_tree->lock); |
|---|
| 158 | 203 | ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, em->start, em->len); |
|---|
| 159 | | - if (ret) |
|---|
| 204 | + write_unlock(&em_tree->lock); |
|---|
| 205 | + if (ret) { |
|---|
| 160 | 206 | test_err("case2 [0 1K]: ret %d", ret); |
|---|
| 207 | + goto out; |
|---|
| 208 | + } |
|---|
| 161 | 209 | if (em && |
|---|
| 162 | 210 | (em->start != 0 || extent_map_end(em) != SZ_1K || |
|---|
| 163 | | - em->block_start != EXTENT_MAP_INLINE || em->block_len != (u64)-1)) |
|---|
| 211 | + em->block_start != EXTENT_MAP_INLINE || em->block_len != (u64)-1)) { |
|---|
| 164 | 212 | test_err( |
|---|
| 165 | 213 | "case2 [0 1K]: ret %d return a wrong em (start %llu len %llu block_start %llu block_len %llu", |
|---|
| 166 | 214 | ret, em->start, em->len, em->block_start, |
|---|
| 167 | 215 | em->block_len); |
|---|
| 216 | + ret = -EINVAL; |
|---|
| 217 | + } |
|---|
| 168 | 218 | free_extent_map(em); |
|---|
| 169 | 219 | out: |
|---|
| 170 | | - /* free memory */ |
|---|
| 171 | 220 | free_extent_map_tree(em_tree); |
|---|
| 221 | + |
|---|
| 222 | + return ret; |
|---|
| 172 | 223 | } |
|---|
| 173 | 224 | |
|---|
| 174 | | -static void __test_case_3(struct btrfs_fs_info *fs_info, |
|---|
| 225 | +static int __test_case_3(struct btrfs_fs_info *fs_info, |
|---|
| 175 | 226 | struct extent_map_tree *em_tree, u64 start) |
|---|
| 176 | 227 | { |
|---|
| 177 | 228 | struct extent_map *em; |
|---|
| .. | .. |
|---|
| 179 | 230 | int ret; |
|---|
| 180 | 231 | |
|---|
| 181 | 232 | em = alloc_extent_map(); |
|---|
| 182 | | - if (!em) |
|---|
| 183 | | - /* Skip this test on error. */ |
|---|
| 184 | | - return; |
|---|
| 233 | + if (!em) { |
|---|
| 234 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
|---|
| 235 | + return -ENOMEM; |
|---|
| 236 | + } |
|---|
| 185 | 237 | |
|---|
| 186 | 238 | /* Add [4K, 8K) */ |
|---|
| 187 | 239 | em->start = SZ_4K; |
|---|
| 188 | 240 | em->len = SZ_4K; |
|---|
| 189 | 241 | em->block_start = SZ_4K; |
|---|
| 190 | 242 | em->block_len = SZ_4K; |
|---|
| 243 | + write_lock(&em_tree->lock); |
|---|
| 191 | 244 | ret = add_extent_mapping(em_tree, em, 0); |
|---|
| 192 | | - ASSERT(ret == 0); |
|---|
| 245 | + write_unlock(&em_tree->lock); |
|---|
| 246 | + if (ret < 0) { |
|---|
| 247 | + test_err("cannot add extent range [4K, 8K)"); |
|---|
| 248 | + goto out; |
|---|
| 249 | + } |
|---|
| 193 | 250 | free_extent_map(em); |
|---|
| 194 | 251 | |
|---|
| 195 | 252 | em = alloc_extent_map(); |
|---|
| 196 | | - if (!em) |
|---|
| 253 | + if (!em) { |
|---|
| 254 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
|---|
| 255 | + ret = -ENOMEM; |
|---|
| 197 | 256 | goto out; |
|---|
| 257 | + } |
|---|
| 198 | 258 | |
|---|
| 199 | 259 | /* Add [0, 16K) */ |
|---|
| 200 | 260 | em->start = 0; |
|---|
| 201 | 261 | em->len = SZ_16K; |
|---|
| 202 | 262 | em->block_start = 0; |
|---|
| 203 | 263 | em->block_len = SZ_16K; |
|---|
| 264 | + write_lock(&em_tree->lock); |
|---|
| 204 | 265 | ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, start, len); |
|---|
| 205 | | - if (ret) |
|---|
| 266 | + write_unlock(&em_tree->lock); |
|---|
| 267 | + if (ret) { |
|---|
| 206 | 268 | test_err("case3 [0x%llx 0x%llx): ret %d", |
|---|
| 207 | 269 | start, start + len, ret); |
|---|
| 270 | + goto out; |
|---|
| 271 | + } |
|---|
| 208 | 272 | /* |
|---|
| 209 | 273 | * Since bytes within em are contiguous, em->block_start is identical to |
|---|
| 210 | 274 | * em->start. |
|---|
| 211 | 275 | */ |
|---|
| 212 | 276 | if (em && |
|---|
| 213 | 277 | (start < em->start || start + len > extent_map_end(em) || |
|---|
| 214 | | - em->start != em->block_start || em->len != em->block_len)) |
|---|
| 278 | + em->start != em->block_start || em->len != em->block_len)) { |
|---|
| 215 | 279 | test_err( |
|---|
| 216 | 280 | "case3 [0x%llx 0x%llx): ret %d em (start 0x%llx len 0x%llx block_start 0x%llx block_len 0x%llx)", |
|---|
| 217 | 281 | start, start + len, ret, em->start, em->len, |
|---|
| 218 | 282 | em->block_start, em->block_len); |
|---|
| 283 | + ret = -EINVAL; |
|---|
| 284 | + } |
|---|
| 219 | 285 | free_extent_map(em); |
|---|
| 220 | 286 | out: |
|---|
| 221 | | - /* free memory */ |
|---|
| 222 | 287 | free_extent_map_tree(em_tree); |
|---|
| 288 | + |
|---|
| 289 | + return ret; |
|---|
| 223 | 290 | } |
|---|
| 224 | 291 | |
|---|
| 225 | 292 | /* |
|---|
| .. | .. |
|---|
| 238 | 305 | * -> add_extent_mapping() |
|---|
| 239 | 306 | * -> add_extent_mapping() |
|---|
| 240 | 307 | */ |
|---|
| 241 | | -static void test_case_3(struct btrfs_fs_info *fs_info, |
|---|
| 308 | +static int test_case_3(struct btrfs_fs_info *fs_info, |
|---|
| 242 | 309 | struct extent_map_tree *em_tree) |
|---|
| 243 | 310 | { |
|---|
| 244 | | - __test_case_3(fs_info, em_tree, 0); |
|---|
| 245 | | - __test_case_3(fs_info, em_tree, SZ_8K); |
|---|
| 246 | | - __test_case_3(fs_info, em_tree, (12 * 1024ULL)); |
|---|
| 311 | + int ret; |
|---|
| 312 | + |
|---|
| 313 | + ret = __test_case_3(fs_info, em_tree, 0); |
|---|
| 314 | + if (ret) |
|---|
| 315 | + return ret; |
|---|
| 316 | + ret = __test_case_3(fs_info, em_tree, SZ_8K); |
|---|
| 317 | + if (ret) |
|---|
| 318 | + return ret; |
|---|
| 319 | + ret = __test_case_3(fs_info, em_tree, (12 * SZ_1K)); |
|---|
| 320 | + |
|---|
| 321 | + return ret; |
|---|
| 247 | 322 | } |
|---|
| 248 | 323 | |
|---|
| 249 | | -static void __test_case_4(struct btrfs_fs_info *fs_info, |
|---|
| 324 | +static int __test_case_4(struct btrfs_fs_info *fs_info, |
|---|
| 250 | 325 | struct extent_map_tree *em_tree, u64 start) |
|---|
| 251 | 326 | { |
|---|
| 252 | 327 | struct extent_map *em; |
|---|
| .. | .. |
|---|
| 254 | 329 | int ret; |
|---|
| 255 | 330 | |
|---|
| 256 | 331 | em = alloc_extent_map(); |
|---|
| 257 | | - if (!em) |
|---|
| 258 | | - /* Skip this test on error. */ |
|---|
| 259 | | - return; |
|---|
| 332 | + if (!em) { |
|---|
| 333 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
|---|
| 334 | + return -ENOMEM; |
|---|
| 335 | + } |
|---|
| 260 | 336 | |
|---|
| 261 | 337 | /* Add [0K, 8K) */ |
|---|
| 262 | 338 | em->start = 0; |
|---|
| 263 | 339 | em->len = SZ_8K; |
|---|
| 264 | 340 | em->block_start = 0; |
|---|
| 265 | 341 | em->block_len = SZ_8K; |
|---|
| 342 | + write_lock(&em_tree->lock); |
|---|
| 266 | 343 | ret = add_extent_mapping(em_tree, em, 0); |
|---|
| 267 | | - ASSERT(ret == 0); |
|---|
| 344 | + write_unlock(&em_tree->lock); |
|---|
| 345 | + if (ret < 0) { |
|---|
| 346 | + test_err("cannot add extent range [0, 8K)"); |
|---|
| 347 | + goto out; |
|---|
| 348 | + } |
|---|
| 268 | 349 | free_extent_map(em); |
|---|
| 269 | 350 | |
|---|
| 270 | 351 | em = alloc_extent_map(); |
|---|
| 271 | | - if (!em) |
|---|
| 352 | + if (!em) { |
|---|
| 353 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
|---|
| 354 | + ret = -ENOMEM; |
|---|
| 272 | 355 | goto out; |
|---|
| 356 | + } |
|---|
| 273 | 357 | |
|---|
| 274 | | - /* Add [8K, 24K) */ |
|---|
| 358 | + /* Add [8K, 32K) */ |
|---|
| 275 | 359 | em->start = SZ_8K; |
|---|
| 276 | | - em->len = 24 * 1024ULL; |
|---|
| 360 | + em->len = 24 * SZ_1K; |
|---|
| 277 | 361 | em->block_start = SZ_16K; /* avoid merging */ |
|---|
| 278 | | - em->block_len = 24 * 1024ULL; |
|---|
| 362 | + em->block_len = 24 * SZ_1K; |
|---|
| 363 | + write_lock(&em_tree->lock); |
|---|
| 279 | 364 | ret = add_extent_mapping(em_tree, em, 0); |
|---|
| 280 | | - ASSERT(ret == 0); |
|---|
| 365 | + write_unlock(&em_tree->lock); |
|---|
| 366 | + if (ret < 0) { |
|---|
| 367 | + test_err("cannot add extent range [8K, 32K)"); |
|---|
| 368 | + goto out; |
|---|
| 369 | + } |
|---|
| 281 | 370 | free_extent_map(em); |
|---|
| 282 | 371 | |
|---|
| 283 | 372 | em = alloc_extent_map(); |
|---|
| 284 | | - if (!em) |
|---|
| 373 | + if (!em) { |
|---|
| 374 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
|---|
| 375 | + ret = -ENOMEM; |
|---|
| 285 | 376 | goto out; |
|---|
| 377 | + } |
|---|
| 286 | 378 | /* Add [0K, 32K) */ |
|---|
| 287 | 379 | em->start = 0; |
|---|
| 288 | 380 | em->len = SZ_32K; |
|---|
| 289 | 381 | em->block_start = 0; |
|---|
| 290 | 382 | em->block_len = SZ_32K; |
|---|
| 383 | + write_lock(&em_tree->lock); |
|---|
| 291 | 384 | ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, start, len); |
|---|
| 292 | | - if (ret) |
|---|
| 385 | + write_unlock(&em_tree->lock); |
|---|
| 386 | + if (ret) { |
|---|
| 293 | 387 | test_err("case4 [0x%llx 0x%llx): ret %d", |
|---|
| 294 | 388 | start, len, ret); |
|---|
| 295 | | - if (em && |
|---|
| 296 | | - (start < em->start || start + len > extent_map_end(em))) |
|---|
| 389 | + goto out; |
|---|
| 390 | + } |
|---|
| 391 | + if (em && (start < em->start || start + len > extent_map_end(em))) { |
|---|
| 297 | 392 | test_err( |
|---|
| 298 | 393 | "case4 [0x%llx 0x%llx): ret %d, added wrong em (start 0x%llx len 0x%llx block_start 0x%llx block_len 0x%llx)", |
|---|
| 299 | 394 | start, len, ret, em->start, em->len, em->block_start, |
|---|
| 300 | 395 | em->block_len); |
|---|
| 396 | + ret = -EINVAL; |
|---|
| 397 | + } |
|---|
| 301 | 398 | free_extent_map(em); |
|---|
| 302 | 399 | out: |
|---|
| 303 | | - /* free memory */ |
|---|
| 304 | 400 | free_extent_map_tree(em_tree); |
|---|
| 401 | + |
|---|
| 402 | + return ret; |
|---|
| 305 | 403 | } |
|---|
| 306 | 404 | |
|---|
| 307 | 405 | /* |
|---|
| .. | .. |
|---|
| 329 | 427 | * # handle -EEXIST when adding |
|---|
| 330 | 428 | * # [0, 32K) |
|---|
| 331 | 429 | */ |
|---|
| 332 | | -static void test_case_4(struct btrfs_fs_info *fs_info, |
|---|
| 430 | +static int test_case_4(struct btrfs_fs_info *fs_info, |
|---|
| 333 | 431 | struct extent_map_tree *em_tree) |
|---|
| 334 | 432 | { |
|---|
| 335 | | - __test_case_4(fs_info, em_tree, 0); |
|---|
| 336 | | - __test_case_4(fs_info, em_tree, SZ_4K); |
|---|
| 433 | + int ret; |
|---|
| 434 | + |
|---|
| 435 | + ret = __test_case_4(fs_info, em_tree, 0); |
|---|
| 436 | + if (ret) |
|---|
| 437 | + return ret; |
|---|
| 438 | + ret = __test_case_4(fs_info, em_tree, SZ_4K); |
|---|
| 439 | + |
|---|
| 440 | + return ret; |
|---|
| 441 | +} |
|---|
| 442 | + |
|---|
| 443 | +struct rmap_test_vector { |
|---|
| 444 | + u64 raid_type; |
|---|
| 445 | + u64 physical_start; |
|---|
| 446 | + u64 data_stripe_size; |
|---|
| 447 | + u64 num_data_stripes; |
|---|
| 448 | + u64 num_stripes; |
|---|
| 449 | + /* Assume we won't have more than 5 physical stripes */ |
|---|
| 450 | + u64 data_stripe_phys_start[5]; |
|---|
| 451 | + bool expected_mapped_addr; |
|---|
| 452 | + /* Physical to logical addresses */ |
|---|
| 453 | + u64 mapped_logical[5]; |
|---|
| 454 | +}; |
|---|
| 455 | + |
|---|
| 456 | +static int test_rmap_block(struct btrfs_fs_info *fs_info, |
|---|
| 457 | + struct rmap_test_vector *test) |
|---|
| 458 | +{ |
|---|
| 459 | + struct extent_map *em; |
|---|
| 460 | + struct map_lookup *map = NULL; |
|---|
| 461 | + u64 *logical = NULL; |
|---|
| 462 | + int i, out_ndaddrs, out_stripe_len; |
|---|
| 463 | + int ret; |
|---|
| 464 | + |
|---|
| 465 | + em = alloc_extent_map(); |
|---|
| 466 | + if (!em) { |
|---|
| 467 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
|---|
| 468 | + return -ENOMEM; |
|---|
| 469 | + } |
|---|
| 470 | + |
|---|
| 471 | + map = kmalloc(map_lookup_size(test->num_stripes), GFP_KERNEL); |
|---|
| 472 | + if (!map) { |
|---|
| 473 | + kfree(em); |
|---|
| 474 | + test_std_err(TEST_ALLOC_EXTENT_MAP); |
|---|
| 475 | + return -ENOMEM; |
|---|
| 476 | + } |
|---|
| 477 | + |
|---|
| 478 | + set_bit(EXTENT_FLAG_FS_MAPPING, &em->flags); |
|---|
| 479 | + /* Start at 4GiB logical address */ |
|---|
| 480 | + em->start = SZ_4G; |
|---|
| 481 | + em->len = test->data_stripe_size * test->num_data_stripes; |
|---|
| 482 | + em->block_len = em->len; |
|---|
| 483 | + em->orig_block_len = test->data_stripe_size; |
|---|
| 484 | + em->map_lookup = map; |
|---|
| 485 | + |
|---|
| 486 | + map->num_stripes = test->num_stripes; |
|---|
| 487 | + map->stripe_len = BTRFS_STRIPE_LEN; |
|---|
| 488 | + map->type = test->raid_type; |
|---|
| 489 | + |
|---|
| 490 | + for (i = 0; i < map->num_stripes; i++) { |
|---|
| 491 | + struct btrfs_device *dev = btrfs_alloc_dummy_device(fs_info); |
|---|
| 492 | + |
|---|
| 493 | + if (IS_ERR(dev)) { |
|---|
| 494 | + test_err("cannot allocate device"); |
|---|
| 495 | + ret = PTR_ERR(dev); |
|---|
| 496 | + goto out; |
|---|
| 497 | + } |
|---|
| 498 | + map->stripes[i].dev = dev; |
|---|
| 499 | + map->stripes[i].physical = test->data_stripe_phys_start[i]; |
|---|
| 500 | + } |
|---|
| 501 | + |
|---|
| 502 | + write_lock(&fs_info->mapping_tree.lock); |
|---|
| 503 | + ret = add_extent_mapping(&fs_info->mapping_tree, em, 0); |
|---|
| 504 | + write_unlock(&fs_info->mapping_tree.lock); |
|---|
| 505 | + if (ret) { |
|---|
| 506 | + test_err("error adding block group mapping to mapping tree"); |
|---|
| 507 | + goto out_free; |
|---|
| 508 | + } |
|---|
| 509 | + |
|---|
| 510 | + ret = btrfs_rmap_block(fs_info, em->start, btrfs_sb_offset(1), |
|---|
| 511 | + &logical, &out_ndaddrs, &out_stripe_len); |
|---|
| 512 | + if (ret || (out_ndaddrs == 0 && test->expected_mapped_addr)) { |
|---|
| 513 | + test_err("didn't rmap anything but expected %d", |
|---|
| 514 | + test->expected_mapped_addr); |
|---|
| 515 | + goto out; |
|---|
| 516 | + } |
|---|
| 517 | + |
|---|
| 518 | + if (out_stripe_len != BTRFS_STRIPE_LEN) { |
|---|
| 519 | + test_err("calculated stripe length doesn't match"); |
|---|
| 520 | + goto out; |
|---|
| 521 | + } |
|---|
| 522 | + |
|---|
| 523 | + if (out_ndaddrs != test->expected_mapped_addr) { |
|---|
| 524 | + for (i = 0; i < out_ndaddrs; i++) |
|---|
| 525 | + test_msg("mapped %llu", logical[i]); |
|---|
| 526 | + test_err("unexpected number of mapped addresses: %d", out_ndaddrs); |
|---|
| 527 | + goto out; |
|---|
| 528 | + } |
|---|
| 529 | + |
|---|
| 530 | + for (i = 0; i < out_ndaddrs; i++) { |
|---|
| 531 | + if (logical[i] != test->mapped_logical[i]) { |
|---|
| 532 | + test_err("unexpected logical address mapped"); |
|---|
| 533 | + goto out; |
|---|
| 534 | + } |
|---|
| 535 | + } |
|---|
| 536 | + |
|---|
| 537 | + ret = 0; |
|---|
| 538 | +out: |
|---|
| 539 | + write_lock(&fs_info->mapping_tree.lock); |
|---|
| 540 | + remove_extent_mapping(&fs_info->mapping_tree, em); |
|---|
| 541 | + write_unlock(&fs_info->mapping_tree.lock); |
|---|
| 542 | + /* For us */ |
|---|
| 543 | + free_extent_map(em); |
|---|
| 544 | +out_free: |
|---|
| 545 | + /* For the tree */ |
|---|
| 546 | + free_extent_map(em); |
|---|
| 547 | + kfree(logical); |
|---|
| 548 | + return ret; |
|---|
| 337 | 549 | } |
|---|
| 338 | 550 | |
|---|
| 339 | 551 | int btrfs_test_extent_map(void) |
|---|
| 340 | 552 | { |
|---|
| 341 | 553 | struct btrfs_fs_info *fs_info = NULL; |
|---|
| 342 | 554 | struct extent_map_tree *em_tree; |
|---|
| 555 | + int ret = 0, i; |
|---|
| 556 | + struct rmap_test_vector rmap_tests[] = { |
|---|
| 557 | + { |
|---|
| 558 | + /* |
|---|
| 559 | + * Test a chunk with 2 data stripes one of which |
|---|
| 560 | + * interesects the physical address of the super block |
|---|
| 561 | + * is correctly recognised. |
|---|
| 562 | + */ |
|---|
| 563 | + .raid_type = BTRFS_BLOCK_GROUP_RAID1, |
|---|
| 564 | + .physical_start = SZ_64M - SZ_4M, |
|---|
| 565 | + .data_stripe_size = SZ_256M, |
|---|
| 566 | + .num_data_stripes = 2, |
|---|
| 567 | + .num_stripes = 2, |
|---|
| 568 | + .data_stripe_phys_start = |
|---|
| 569 | + {SZ_64M - SZ_4M, SZ_64M - SZ_4M + SZ_256M}, |
|---|
| 570 | + .expected_mapped_addr = true, |
|---|
| 571 | + .mapped_logical= {SZ_4G + SZ_4M} |
|---|
| 572 | + }, |
|---|
| 573 | + { |
|---|
| 574 | + /* |
|---|
| 575 | + * Test that out-of-range physical addresses are |
|---|
| 576 | + * ignored |
|---|
| 577 | + */ |
|---|
| 578 | + |
|---|
| 579 | + /* SINGLE chunk type */ |
|---|
| 580 | + .raid_type = 0, |
|---|
| 581 | + .physical_start = SZ_4G, |
|---|
| 582 | + .data_stripe_size = SZ_256M, |
|---|
| 583 | + .num_data_stripes = 1, |
|---|
| 584 | + .num_stripes = 1, |
|---|
| 585 | + .data_stripe_phys_start = {SZ_256M}, |
|---|
| 586 | + .expected_mapped_addr = false, |
|---|
| 587 | + .mapped_logical = {0} |
|---|
| 588 | + } |
|---|
| 589 | + }; |
|---|
| 343 | 590 | |
|---|
| 344 | 591 | test_msg("running extent_map tests"); |
|---|
| 345 | 592 | |
|---|
| .. | .. |
|---|
| 349 | 596 | */ |
|---|
| 350 | 597 | fs_info = btrfs_alloc_dummy_fs_info(PAGE_SIZE, PAGE_SIZE); |
|---|
| 351 | 598 | if (!fs_info) { |
|---|
| 352 | | - test_msg("Couldn't allocate dummy fs info"); |
|---|
| 599 | + test_std_err(TEST_ALLOC_FS_INFO); |
|---|
| 353 | 600 | return -ENOMEM; |
|---|
| 354 | 601 | } |
|---|
| 355 | 602 | |
|---|
| 356 | 603 | em_tree = kzalloc(sizeof(*em_tree), GFP_KERNEL); |
|---|
| 357 | | - if (!em_tree) |
|---|
| 358 | | - /* Skip the test on error. */ |
|---|
| 604 | + if (!em_tree) { |
|---|
| 605 | + ret = -ENOMEM; |
|---|
| 359 | 606 | goto out; |
|---|
| 607 | + } |
|---|
| 360 | 608 | |
|---|
| 361 | 609 | extent_map_tree_init(em_tree); |
|---|
| 362 | 610 | |
|---|
| 363 | | - test_case_1(fs_info, em_tree); |
|---|
| 364 | | - test_case_2(fs_info, em_tree); |
|---|
| 365 | | - test_case_3(fs_info, em_tree); |
|---|
| 366 | | - test_case_4(fs_info, em_tree); |
|---|
| 611 | + ret = test_case_1(fs_info, em_tree); |
|---|
| 612 | + if (ret) |
|---|
| 613 | + goto out; |
|---|
| 614 | + ret = test_case_2(fs_info, em_tree); |
|---|
| 615 | + if (ret) |
|---|
| 616 | + goto out; |
|---|
| 617 | + ret = test_case_3(fs_info, em_tree); |
|---|
| 618 | + if (ret) |
|---|
| 619 | + goto out; |
|---|
| 620 | + ret = test_case_4(fs_info, em_tree); |
|---|
| 367 | 621 | |
|---|
| 368 | | - kfree(em_tree); |
|---|
| 622 | + test_msg("running rmap tests"); |
|---|
| 623 | + for (i = 0; i < ARRAY_SIZE(rmap_tests); i++) { |
|---|
| 624 | + ret = test_rmap_block(fs_info, &rmap_tests[i]); |
|---|
| 625 | + if (ret) |
|---|
| 626 | + goto out; |
|---|
| 627 | + } |
|---|
| 628 | + |
|---|
| 369 | 629 | out: |
|---|
| 630 | + kfree(em_tree); |
|---|
| 370 | 631 | btrfs_free_dummy_fs_info(fs_info); |
|---|
| 371 | 632 | |
|---|
| 372 | | - return 0; |
|---|
| 633 | + return ret; |
|---|
| 373 | 634 | } |
|---|