1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2013 Fusion IO. 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 "../disk-io.h" 11 #include "../extent_io.h" 12 #include "../volumes.h" 13 #include "../compression.h" 14 #include "../accessors.h" 15 16 static void insert_extent(struct btrfs_root *root, u64 start, u64 len, 17 u64 ram_bytes, u64 offset, u64 disk_bytenr, 18 u64 disk_len, u32 type, u8 compression, int slot) 19 { 20 struct btrfs_path path; 21 struct btrfs_file_extent_item *fi; 22 struct extent_buffer *leaf = root->node; 23 struct btrfs_key key; 24 u32 value_len = sizeof(struct btrfs_file_extent_item); 25 26 if (type == BTRFS_FILE_EXTENT_INLINE) 27 value_len += len; 28 memset(&path, 0, sizeof(path)); 29 30 path.nodes[0] = leaf; 31 path.slots[0] = slot; 32 33 key.objectid = BTRFS_FIRST_FREE_OBJECTID; 34 key.type = BTRFS_EXTENT_DATA_KEY; 35 key.offset = start; 36 37 /* 38 * Passing a NULL trans handle is fine here, we have a dummy root eb 39 * and the tree is a single node (level 0). 40 */ 41 btrfs_setup_item_for_insert(NULL, root, &path, &key, value_len); 42 fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); 43 btrfs_set_file_extent_generation(leaf, fi, 1); 44 btrfs_set_file_extent_type(leaf, fi, type); 45 btrfs_set_file_extent_disk_bytenr(leaf, fi, disk_bytenr); 46 btrfs_set_file_extent_disk_num_bytes(leaf, fi, disk_len); 47 btrfs_set_file_extent_offset(leaf, fi, offset); 48 btrfs_set_file_extent_num_bytes(leaf, fi, len); 49 btrfs_set_file_extent_ram_bytes(leaf, fi, ram_bytes); 50 btrfs_set_file_extent_compression(leaf, fi, compression); 51 btrfs_set_file_extent_encryption(leaf, fi, 0); 52 btrfs_set_file_extent_other_encoding(leaf, fi, 0); 53 } 54 55 static void insert_inode_item_key(struct btrfs_root *root) 56 { 57 struct btrfs_path path; 58 struct extent_buffer *leaf = root->node; 59 struct btrfs_key key; 60 u32 value_len = 0; 61 62 memset(&path, 0, sizeof(path)); 63 64 path.nodes[0] = leaf; 65 path.slots[0] = 0; 66 67 key.objectid = BTRFS_INODE_ITEM_KEY; 68 key.type = BTRFS_INODE_ITEM_KEY; 69 key.offset = 0; 70 71 /* 72 * Passing a NULL trans handle is fine here, we have a dummy root eb 73 * and the tree is a single node (level 0). 74 */ 75 btrfs_setup_item_for_insert(NULL, root, &path, &key, value_len); 76 } 77 78 /* 79 * Build the most complicated map of extents the earth has ever seen. We want 80 * this so we can test all of the corner cases of btrfs_get_extent. Here is a 81 * diagram of how the extents will look though this may not be possible we still 82 * want to make sure everything acts normally (the last number is not inclusive) 83 * 84 * The numbers are using 4K fs block size as an example, the real test will scale 85 * all the extent maps (except the inlined one) according to the block size. 86 * 87 * [ 0 - 6 ][ 6 - 4K ][ 4K - 8K ][ 8K - 12K ] 88 * [ inline ][ implied hole ][ regular ][ regular1 split ] 89 * 90 * [ 12K - 16K ][ 16K - 24K ][ 24K - 28K ][ 28K - 32K ][ 32K - 36K ] 91 * [ hole ][ regular1 split ][ prealloc ][ prealloc1 ][ prealloc1 written ] 92 * 93 * [ 36K - 44K ][ 44K - 52K ][ 52K - 56K ][ 56K - 60K ][ 60K - 68 K ] 94 * [ prealloc1 ][ compressed ][ compressed1 ][ regular ][ compressed1 ] 95 * 96 * [ 68K - 72K ][ 72K - 84K ][ 84K - 88K ] 97 * [ regular ][ hole but no extent ][ regular ] 98 */ 99 static void setup_file_extents(struct btrfs_root *root, u32 sectorsize) 100 { 101 int slot = 0; 102 u64 disk_bytenr = SZ_1M; 103 u64 offset = 0; 104 105 /* 106 * Start 0, length 6, inlined. 107 * 108 * Tree-checker has strict limits on inline extents that they can only 109 * exist at file offset 0, thus we can only have one inline file extent 110 * at most. 111 */ 112 insert_extent(root, offset, 6, 6, 0, 0, 0, BTRFS_FILE_EXTENT_INLINE, 0, 113 slot); 114 slot++; 115 offset = sectorsize; 116 117 /* Start 1 * blocksize, length 1 * blocksize, regular. */ 118 insert_extent(root, offset, sectorsize, sectorsize, 0, 119 disk_bytenr, sectorsize, BTRFS_FILE_EXTENT_REG, 0, slot); 120 slot++; 121 122 /* We don't want the regular em merged with the next one. */ 123 disk_bytenr += 2 * sectorsize; 124 offset += sectorsize; 125 126 /* 127 * Start 2 * blocksize, length 1 * blocksize, regular. 128 * 129 * Now for 3 extents that were split from a hole punch so we test 130 * offsets properly. 131 */ 132 insert_extent(root, offset, sectorsize, 4 * sectorsize, 0, disk_bytenr, 133 4 * sectorsize, BTRFS_FILE_EXTENT_REG, 0, slot); 134 slot++; 135 offset += sectorsize; 136 137 /* Start 3 * blocksize, length 1 * blocksize, regular, explicit hole. */ 138 insert_extent(root, offset, sectorsize, sectorsize, 0, 0, 0, 139 BTRFS_FILE_EXTENT_REG, 0, slot); 140 slot++; 141 offset += sectorsize; 142 143 /* Start 4 * blocksize, length 2 * blocksize, regular. */ 144 insert_extent(root, offset, 2 * sectorsize, 4 * sectorsize, 145 2 * sectorsize, disk_bytenr, 4 * sectorsize, 146 BTRFS_FILE_EXTENT_REG, 0, slot); 147 slot++; 148 offset += 2 * sectorsize; 149 disk_bytenr += 4 * sectorsize; 150 151 /* Start 6 * blocksize, length 1 * blocksize, preallocated. */ 152 insert_extent(root, offset, sectorsize, sectorsize, 0, disk_bytenr, 153 sectorsize, BTRFS_FILE_EXTENT_PREALLOC, 0, slot); 154 slot++; 155 offset += sectorsize; 156 157 /* 158 * We want to jack up disk_bytenr a little more so the em stuff doesn't 159 * merge our records. 160 */ 161 disk_bytenr += 2 * sectorsize; 162 163 /* 164 * Start 7 * blocksize, length 1 * blocksize, prealloc. 165 * 166 * Now for a partially written prealloc extent, basically the same as 167 * the hole punch example above. Ram_bytes never changes when you mark 168 * extents written btw. 169 */ 170 insert_extent(root, offset, sectorsize, 4 * sectorsize, 0, disk_bytenr, 171 4 * sectorsize, BTRFS_FILE_EXTENT_PREALLOC, 0, slot); 172 slot++; 173 offset += sectorsize; 174 175 /* Start 8 * blocksize, length 1 * blocksize, regular. */ 176 insert_extent(root, offset, sectorsize, 4 * sectorsize, sectorsize, 177 disk_bytenr, 4 * sectorsize, BTRFS_FILE_EXTENT_REG, 0, 178 slot); 179 slot++; 180 offset += sectorsize; 181 182 /* Start 9 * blocksize, length 2 * blocksize, prealloc. */ 183 insert_extent(root, offset, 2 * sectorsize, 4 * sectorsize, 184 2 * sectorsize, disk_bytenr, 4 * sectorsize, 185 BTRFS_FILE_EXTENT_PREALLOC, 0, slot); 186 slot++; 187 offset += 2 * sectorsize; 188 disk_bytenr += 4 * sectorsize; 189 190 /* Start 11 * blocksize, length 2 * blocksize, regular. */ 191 insert_extent(root, offset, 2 * sectorsize, 2 * sectorsize, 0, 192 disk_bytenr, sectorsize, BTRFS_FILE_EXTENT_REG, 193 BTRFS_COMPRESS_ZLIB, slot); 194 slot++; 195 offset += 2 * sectorsize; 196 /* No merges */ 197 disk_bytenr += 2 * sectorsize; 198 199 /* Start 13 * blocksize, length 1 * blocksize, regular. */ 200 insert_extent(root, offset, sectorsize, 4 * sectorsize, 0, disk_bytenr, 201 sectorsize, BTRFS_FILE_EXTENT_REG, 202 BTRFS_COMPRESS_ZLIB, slot); 203 slot++; 204 offset += sectorsize; 205 206 /* Start 14 * blocksize, length 1 * blocksize, regular. */ 207 insert_extent(root, offset, sectorsize, sectorsize, 0, 208 disk_bytenr + sectorsize, sectorsize, 209 BTRFS_FILE_EXTENT_REG, 0, slot); 210 slot++; 211 offset += sectorsize; 212 213 /* Start 15 * blocksize, length 2 * blocksize, regular. */ 214 insert_extent(root, offset, 2 * sectorsize, 4 * sectorsize, 215 2 * sectorsize, disk_bytenr, sectorsize, 216 BTRFS_FILE_EXTENT_REG, BTRFS_COMPRESS_ZLIB, slot); 217 slot++; 218 offset += 2 * sectorsize; 219 disk_bytenr += 2 * sectorsize; 220 221 /* Start 17 * blocksize, length 1 * blocksize, regular. */ 222 insert_extent(root, offset, sectorsize, sectorsize, 0, disk_bytenr, 223 sectorsize, BTRFS_FILE_EXTENT_REG, 0, slot); 224 slot++; 225 offset += 4 * sectorsize; 226 disk_bytenr += sectorsize; 227 228 /* 229 * Start 18 * blocksize, length 3 * blocksize, implied hole (aka no 230 * file extent item). 231 * 232 * Start 21 * blocksize, length 1 * blocksize, regular. 233 */ 234 insert_extent(root, offset, sectorsize, sectorsize, 0, disk_bytenr, 235 sectorsize, BTRFS_FILE_EXTENT_REG, 0, slot); 236 } 237 238 static u32 prealloc_only = 0; 239 static u32 compressed_only = 0; 240 static u32 vacancy_only = 0; 241 242 static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize) 243 { 244 struct btrfs_fs_info *fs_info = NULL; 245 struct inode *inode = NULL; 246 struct btrfs_root *root = NULL; 247 struct extent_map *em = NULL; 248 u64 orig_start; 249 u64 disk_bytenr; 250 u64 offset; 251 int ret = -ENOMEM; 252 253 test_msg("running btrfs_get_extent tests"); 254 255 inode = btrfs_new_test_inode(); 256 if (!inode) { 257 test_std_err(TEST_ALLOC_INODE); 258 return ret; 259 } 260 261 fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize); 262 if (!fs_info) { 263 test_std_err(TEST_ALLOC_FS_INFO); 264 goto out; 265 } 266 267 root = btrfs_alloc_dummy_root(fs_info); 268 if (IS_ERR(root)) { 269 test_std_err(TEST_ALLOC_ROOT); 270 goto out; 271 } 272 273 root->node = alloc_dummy_extent_buffer(fs_info, nodesize); 274 if (!root->node) { 275 test_std_err(TEST_ALLOC_ROOT); 276 goto out; 277 } 278 279 btrfs_set_header_nritems(root->node, 0); 280 btrfs_set_header_level(root->node, 0); 281 ret = -EINVAL; 282 283 /* First with no extents */ 284 BTRFS_I(inode)->root = root; 285 em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, sectorsize); 286 if (IS_ERR(em)) { 287 em = NULL; 288 test_err("got an error when we shouldn't have"); 289 goto out; 290 } 291 if (em->disk_bytenr != EXTENT_MAP_HOLE) { 292 test_err("expected a hole, got %llu", em->disk_bytenr); 293 goto out; 294 } 295 btrfs_free_extent_map(em); 296 btrfs_drop_extent_map_range(BTRFS_I(inode), 0, (u64)-1, false); 297 298 /* 299 * All of the magic numbers are based on the mapping setup in 300 * setup_file_extents, so if you change anything there you need to 301 * update the comment and update the expected values below. 302 */ 303 setup_file_extents(root, sectorsize); 304 305 em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, (u64)-1); 306 if (IS_ERR(em)) { 307 test_err("got an error when we shouldn't have"); 308 goto out; 309 } 310 if (em->disk_bytenr != EXTENT_MAP_INLINE) { 311 test_err("expected an inline, got %llu", em->disk_bytenr); 312 goto out; 313 } 314 315 /* 316 * For inline extent, we always round up the em to sectorsize, as 317 * they are either: 318 * 319 * a) a hidden hole 320 * The range will be zeroed at inline extent read time. 321 * 322 * b) a file extent with unaligned bytenr 323 * Tree checker will reject it. 324 */ 325 if (em->start != 0 || em->len != sectorsize) { 326 test_err( 327 "unexpected extent wanted start 0 len %u, got start %llu len %llu", 328 sectorsize, em->start, em->len); 329 goto out; 330 } 331 if (em->flags != 0) { 332 test_err("unexpected flags set, want 0 have %u", em->flags); 333 goto out; 334 } 335 /* 336 * We don't test anything else for inline since it doesn't get set 337 * unless we have a page for it to write into. Maybe we should change 338 * this? 339 */ 340 offset = btrfs_extent_map_end(em); 341 btrfs_free_extent_map(em); 342 343 /* Regular extent */ 344 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize); 345 if (IS_ERR(em)) { 346 test_err("got an error when we shouldn't have"); 347 goto out; 348 } 349 if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) { 350 test_err("expected a real extent, got %llu", em->disk_bytenr); 351 goto out; 352 } 353 if (em->start != offset || em->len != sectorsize) { 354 test_err( 355 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 356 offset, sectorsize, em->start, em->len); 357 goto out; 358 } 359 if (em->flags != 0) { 360 test_err("unexpected flags set, want 0 have %u", em->flags); 361 goto out; 362 } 363 if (em->offset != 0) { 364 test_err("wrong offset, want 0, have %llu", em->offset); 365 goto out; 366 } 367 offset = btrfs_extent_map_end(em); 368 btrfs_free_extent_map(em); 369 370 /* The next 3 are split extents */ 371 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize); 372 if (IS_ERR(em)) { 373 test_err("got an error when we shouldn't have"); 374 goto out; 375 } 376 if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) { 377 test_err("expected a real extent, got %llu", em->disk_bytenr); 378 goto out; 379 } 380 if (em->start != offset || em->len != sectorsize) { 381 test_err( 382 "unexpected extent start %llu len %u, got start %llu len %llu", 383 offset, sectorsize, em->start, em->len); 384 goto out; 385 } 386 if (em->flags != 0) { 387 test_err("unexpected flags set, want 0 have %u", em->flags); 388 goto out; 389 } 390 if (em->offset != 0) { 391 test_err("wrong offset, want 0, have %llu", em->offset); 392 goto out; 393 } 394 disk_bytenr = btrfs_extent_map_block_start(em); 395 orig_start = em->start; 396 offset = btrfs_extent_map_end(em); 397 btrfs_free_extent_map(em); 398 399 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize); 400 if (IS_ERR(em)) { 401 test_err("got an error when we shouldn't have"); 402 goto out; 403 } 404 if (em->disk_bytenr != EXTENT_MAP_HOLE) { 405 test_err("expected a hole, got %llu", em->disk_bytenr); 406 goto out; 407 } 408 if (em->start != offset || em->len != sectorsize) { 409 test_err( 410 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 411 offset, sectorsize, em->start, em->len); 412 goto out; 413 } 414 if (em->flags != 0) { 415 test_err("unexpected flags set, want 0 have %u", em->flags); 416 goto out; 417 } 418 offset = btrfs_extent_map_end(em); 419 btrfs_free_extent_map(em); 420 421 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize); 422 if (IS_ERR(em)) { 423 test_err("got an error when we shouldn't have"); 424 goto out; 425 } 426 if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) { 427 test_err("expected a real extent, got %llu", em->disk_bytenr); 428 goto out; 429 } 430 if (em->start != offset || em->len != 2 * sectorsize) { 431 test_err( 432 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 433 offset, 2 * sectorsize, em->start, em->len); 434 goto out; 435 } 436 if (em->flags != 0) { 437 test_err("unexpected flags set, want 0 have %u", em->flags); 438 goto out; 439 } 440 if (em->start - em->offset != orig_start) { 441 test_err("wrong offset, em->start=%llu em->offset=%llu orig_start=%llu", 442 em->start, em->offset, orig_start); 443 goto out; 444 } 445 disk_bytenr += (em->start - orig_start); 446 if (btrfs_extent_map_block_start(em) != disk_bytenr) { 447 test_err("wrong block start, want %llu, have %llu", 448 disk_bytenr, btrfs_extent_map_block_start(em)); 449 goto out; 450 } 451 offset = btrfs_extent_map_end(em); 452 btrfs_free_extent_map(em); 453 454 /* Prealloc extent */ 455 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize); 456 if (IS_ERR(em)) { 457 test_err("got an error when we shouldn't have"); 458 goto out; 459 } 460 if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) { 461 test_err("expected a real extent, got %llu", em->disk_bytenr); 462 goto out; 463 } 464 if (em->start != offset || em->len != sectorsize) { 465 test_err( 466 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 467 offset, sectorsize, em->start, em->len); 468 goto out; 469 } 470 if (em->flags != prealloc_only) { 471 test_err("unexpected flags set, want %u have %u", 472 prealloc_only, em->flags); 473 goto out; 474 } 475 if (em->offset != 0) { 476 test_err("wrong offset, want 0, have %llu", em->offset); 477 goto out; 478 } 479 offset = btrfs_extent_map_end(em); 480 btrfs_free_extent_map(em); 481 482 /* The next 3 are a half written prealloc extent */ 483 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize); 484 if (IS_ERR(em)) { 485 test_err("got an error when we shouldn't have"); 486 goto out; 487 } 488 if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) { 489 test_err("expected a real extent, got %llu", em->disk_bytenr); 490 goto out; 491 } 492 if (em->start != offset || em->len != sectorsize) { 493 test_err( 494 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 495 offset, sectorsize, em->start, em->len); 496 goto out; 497 } 498 if (em->flags != prealloc_only) { 499 test_err("unexpected flags set, want %u have %u", 500 prealloc_only, em->flags); 501 goto out; 502 } 503 if (em->offset != 0) { 504 test_err("wrong offset, want 0, have %llu", em->offset); 505 goto out; 506 } 507 disk_bytenr = btrfs_extent_map_block_start(em); 508 orig_start = em->start; 509 offset = btrfs_extent_map_end(em); 510 btrfs_free_extent_map(em); 511 512 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize); 513 if (IS_ERR(em)) { 514 test_err("got an error when we shouldn't have"); 515 goto out; 516 } 517 if (em->disk_bytenr >= EXTENT_MAP_HOLE) { 518 test_err("expected a real extent, got %llu", em->disk_bytenr); 519 goto out; 520 } 521 if (em->start != offset || em->len != sectorsize) { 522 test_err( 523 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 524 offset, sectorsize, em->start, em->len); 525 goto out; 526 } 527 if (em->flags != 0) { 528 test_err("unexpected flags set, want 0 have %u", em->flags); 529 goto out; 530 } 531 if (em->start - em->offset != orig_start) { 532 test_err("unexpected offset, wanted %llu, have %llu", 533 em->start - orig_start, em->offset); 534 goto out; 535 } 536 if (btrfs_extent_map_block_start(em) != disk_bytenr + em->offset) { 537 test_err("unexpected block start, wanted %llu, have %llu", 538 disk_bytenr + em->offset, btrfs_extent_map_block_start(em)); 539 goto out; 540 } 541 offset = btrfs_extent_map_end(em); 542 btrfs_free_extent_map(em); 543 544 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize); 545 if (IS_ERR(em)) { 546 test_err("got an error when we shouldn't have"); 547 goto out; 548 } 549 if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) { 550 test_err("expected a real extent, got %llu", em->disk_bytenr); 551 goto out; 552 } 553 if (em->start != offset || em->len != 2 * sectorsize) { 554 test_err( 555 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 556 offset, 2 * sectorsize, em->start, em->len); 557 goto out; 558 } 559 if (em->flags != prealloc_only) { 560 test_err("unexpected flags set, want %u have %u", 561 prealloc_only, em->flags); 562 goto out; 563 } 564 if (em->start - em->offset != orig_start) { 565 test_err("wrong offset, em->start=%llu em->offset=%llu orig_start=%llu", 566 em->start, em->offset, orig_start); 567 goto out; 568 } 569 if (btrfs_extent_map_block_start(em) != disk_bytenr + em->offset) { 570 test_err("unexpected block start, wanted %llu, have %llu", 571 disk_bytenr + em->offset, btrfs_extent_map_block_start(em)); 572 goto out; 573 } 574 offset = btrfs_extent_map_end(em); 575 btrfs_free_extent_map(em); 576 577 /* Now for the compressed extent */ 578 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize); 579 if (IS_ERR(em)) { 580 test_err("got an error when we shouldn't have"); 581 goto out; 582 } 583 if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) { 584 test_err("expected a real extent, got %llu", em->disk_bytenr); 585 goto out; 586 } 587 if (em->start != offset || em->len != 2 * sectorsize) { 588 test_err( 589 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 590 offset, 2 * sectorsize, em->start, em->len); 591 goto out; 592 } 593 if (em->flags != compressed_only) { 594 test_err("unexpected flags set, want %u have %u", 595 compressed_only, em->flags); 596 goto out; 597 } 598 if (em->offset != 0) { 599 test_err("wrong offset, want 0, have %llu", em->offset); 600 goto out; 601 } 602 if (btrfs_extent_map_compression(em) != BTRFS_COMPRESS_ZLIB) { 603 test_err("unexpected compress type, wanted %d, got %d", 604 BTRFS_COMPRESS_ZLIB, btrfs_extent_map_compression(em)); 605 goto out; 606 } 607 offset = btrfs_extent_map_end(em); 608 btrfs_free_extent_map(em); 609 610 /* Split compressed extent */ 611 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize); 612 if (IS_ERR(em)) { 613 test_err("got an error when we shouldn't have"); 614 goto out; 615 } 616 if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) { 617 test_err("expected a real extent, got %llu", em->disk_bytenr); 618 goto out; 619 } 620 if (em->start != offset || em->len != sectorsize) { 621 test_err( 622 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 623 offset, sectorsize, em->start, em->len); 624 goto out; 625 } 626 if (em->flags != compressed_only) { 627 test_err("unexpected flags set, want %u have %u", 628 compressed_only, em->flags); 629 goto out; 630 } 631 if (em->offset != 0) { 632 test_err("wrong offset, want 0, have %llu", em->offset); 633 goto out; 634 } 635 if (btrfs_extent_map_compression(em) != BTRFS_COMPRESS_ZLIB) { 636 test_err("unexpected compress type, wanted %d, got %d", 637 BTRFS_COMPRESS_ZLIB, btrfs_extent_map_compression(em)); 638 goto out; 639 } 640 disk_bytenr = btrfs_extent_map_block_start(em); 641 orig_start = em->start; 642 offset = btrfs_extent_map_end(em); 643 btrfs_free_extent_map(em); 644 645 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize); 646 if (IS_ERR(em)) { 647 test_err("got an error when we shouldn't have"); 648 goto out; 649 } 650 if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) { 651 test_err("expected a real extent, got %llu", em->disk_bytenr); 652 goto out; 653 } 654 if (em->start != offset || em->len != sectorsize) { 655 test_err( 656 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 657 offset, sectorsize, em->start, em->len); 658 goto out; 659 } 660 if (em->flags != 0) { 661 test_err("unexpected flags set, want 0 have %u", em->flags); 662 goto out; 663 } 664 if (em->offset != 0) { 665 test_err("wrong offset, want 0, have %llu", em->offset); 666 goto out; 667 } 668 offset = btrfs_extent_map_end(em); 669 btrfs_free_extent_map(em); 670 671 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize); 672 if (IS_ERR(em)) { 673 test_err("got an error when we shouldn't have"); 674 goto out; 675 } 676 if (btrfs_extent_map_block_start(em) != disk_bytenr) { 677 test_err("block start does not match, want %llu got %llu", 678 disk_bytenr, btrfs_extent_map_block_start(em)); 679 goto out; 680 } 681 if (em->start != offset || em->len != 2 * sectorsize) { 682 test_err( 683 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 684 offset, 2 * sectorsize, em->start, em->len); 685 goto out; 686 } 687 if (em->flags != compressed_only) { 688 test_err("unexpected flags set, want %u have %u", 689 compressed_only, em->flags); 690 goto out; 691 } 692 if (em->start - em->offset != orig_start) { 693 test_err("wrong offset, em->start=%llu em->offset=%llu orig_start=%llu", 694 em->start, em->offset, orig_start); 695 goto out; 696 } 697 if (btrfs_extent_map_compression(em) != BTRFS_COMPRESS_ZLIB) { 698 test_err("unexpected compress type, wanted %d, got %d", 699 BTRFS_COMPRESS_ZLIB, btrfs_extent_map_compression(em)); 700 goto out; 701 } 702 offset = btrfs_extent_map_end(em); 703 btrfs_free_extent_map(em); 704 705 /* A hole between regular extents but no hole extent */ 706 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset + 6, sectorsize); 707 if (IS_ERR(em)) { 708 test_err("got an error when we shouldn't have"); 709 goto out; 710 } 711 if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) { 712 test_err("expected a real extent, got %llu", em->disk_bytenr); 713 goto out; 714 } 715 if (em->start != offset || em->len != sectorsize) { 716 test_err( 717 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 718 offset, sectorsize, em->start, em->len); 719 goto out; 720 } 721 if (em->flags != 0) { 722 test_err("unexpected flags set, want 0 have %u", em->flags); 723 goto out; 724 } 725 if (em->offset != 0) { 726 test_err("wrong offset, want 0, have %llu", em->offset); 727 goto out; 728 } 729 offset = btrfs_extent_map_end(em); 730 btrfs_free_extent_map(em); 731 732 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, SZ_4M); 733 if (IS_ERR(em)) { 734 test_err("got an error when we shouldn't have"); 735 goto out; 736 } 737 if (em->disk_bytenr != EXTENT_MAP_HOLE) { 738 test_err("expected a hole extent, got %llu", em->disk_bytenr); 739 goto out; 740 } 741 /* 742 * Currently we just return a length that we requested rather than the 743 * length of the actual hole, if this changes we'll have to change this 744 * test. 745 */ 746 if (em->start != offset || em->len != 3 * sectorsize) { 747 test_err( 748 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 749 offset, 3 * sectorsize, em->start, em->len); 750 goto out; 751 } 752 if (em->flags != vacancy_only) { 753 test_err("unexpected flags set, want %u have %u", 754 vacancy_only, em->flags); 755 goto out; 756 } 757 if (em->offset != 0) { 758 test_err("wrong offset, want 0, have %llu", em->offset); 759 goto out; 760 } 761 offset = btrfs_extent_map_end(em); 762 btrfs_free_extent_map(em); 763 764 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize); 765 if (IS_ERR(em)) { 766 test_err("got an error when we shouldn't have"); 767 goto out; 768 } 769 if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) { 770 test_err("expected a real extent, got %llu", em->disk_bytenr); 771 goto out; 772 } 773 if (em->start != offset || em->len != sectorsize) { 774 test_err( 775 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 776 offset, sectorsize, em->start, em->len); 777 goto out; 778 } 779 if (em->flags != 0) { 780 test_err("unexpected flags set, want 0 have %u", em->flags); 781 goto out; 782 } 783 if (em->offset != 0) { 784 test_err("wrong orig offset, want 0, have %llu", em->offset); 785 goto out; 786 } 787 ret = 0; 788 out: 789 if (!IS_ERR(em)) 790 btrfs_free_extent_map(em); 791 iput(inode); 792 btrfs_free_dummy_root(root); 793 btrfs_free_dummy_fs_info(fs_info); 794 return ret; 795 } 796 797 static int test_hole_first(u32 sectorsize, u32 nodesize) 798 { 799 struct btrfs_fs_info *fs_info = NULL; 800 struct inode *inode = NULL; 801 struct btrfs_root *root = NULL; 802 struct extent_map *em = NULL; 803 int ret = -ENOMEM; 804 805 test_msg("running hole first btrfs_get_extent test"); 806 807 inode = btrfs_new_test_inode(); 808 if (!inode) { 809 test_std_err(TEST_ALLOC_INODE); 810 return ret; 811 } 812 813 fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize); 814 if (!fs_info) { 815 test_std_err(TEST_ALLOC_FS_INFO); 816 goto out; 817 } 818 819 root = btrfs_alloc_dummy_root(fs_info); 820 if (IS_ERR(root)) { 821 test_std_err(TEST_ALLOC_ROOT); 822 goto out; 823 } 824 825 root->node = alloc_dummy_extent_buffer(fs_info, nodesize); 826 if (!root->node) { 827 test_std_err(TEST_ALLOC_ROOT); 828 goto out; 829 } 830 831 btrfs_set_header_nritems(root->node, 0); 832 btrfs_set_header_level(root->node, 0); 833 BTRFS_I(inode)->root = root; 834 ret = -EINVAL; 835 836 /* 837 * Need a blank inode item here just so we don't confuse 838 * btrfs_get_extent. 839 */ 840 insert_inode_item_key(root); 841 insert_extent(root, sectorsize, sectorsize, sectorsize, 0, sectorsize, 842 sectorsize, BTRFS_FILE_EXTENT_REG, 0, 1); 843 em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, 2 * sectorsize); 844 if (IS_ERR(em)) { 845 test_err("got an error when we shouldn't have"); 846 goto out; 847 } 848 if (em->disk_bytenr != EXTENT_MAP_HOLE) { 849 test_err("expected a hole, got %llu", em->disk_bytenr); 850 goto out; 851 } 852 if (em->start != 0 || em->len != sectorsize) { 853 test_err( 854 "unexpected extent wanted start 0 len %u, got start %llu len %llu", 855 sectorsize, em->start, em->len); 856 goto out; 857 } 858 if (em->flags != vacancy_only) { 859 test_err("wrong flags, wanted %u, have %u", vacancy_only, 860 em->flags); 861 goto out; 862 } 863 btrfs_free_extent_map(em); 864 865 em = btrfs_get_extent(BTRFS_I(inode), NULL, sectorsize, 2 * sectorsize); 866 if (IS_ERR(em)) { 867 test_err("got an error when we shouldn't have"); 868 goto out; 869 } 870 if (btrfs_extent_map_block_start(em) != sectorsize) { 871 test_err("expected a real extent, got %llu", 872 btrfs_extent_map_block_start(em)); 873 goto out; 874 } 875 if (em->start != sectorsize || em->len != sectorsize) { 876 test_err( 877 "unexpected extent wanted start %u len %u, got start %llu len %llu", 878 sectorsize, sectorsize, em->start, em->len); 879 goto out; 880 } 881 if (em->flags != 0) { 882 test_err("unexpected flags set, wanted 0 got %u", 883 em->flags); 884 goto out; 885 } 886 ret = 0; 887 out: 888 if (!IS_ERR(em)) 889 btrfs_free_extent_map(em); 890 iput(inode); 891 btrfs_free_dummy_root(root); 892 btrfs_free_dummy_fs_info(fs_info); 893 return ret; 894 } 895 896 static int test_extent_accounting(u32 sectorsize, u32 nodesize) 897 { 898 struct btrfs_fs_info *fs_info = NULL; 899 struct inode *inode = NULL; 900 struct btrfs_root *root = NULL; 901 int ret = -ENOMEM; 902 903 test_msg("running outstanding_extents tests"); 904 905 inode = btrfs_new_test_inode(); 906 if (!inode) { 907 test_std_err(TEST_ALLOC_INODE); 908 return ret; 909 } 910 911 fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize); 912 if (!fs_info) { 913 test_std_err(TEST_ALLOC_FS_INFO); 914 goto out; 915 } 916 917 root = btrfs_alloc_dummy_root(fs_info); 918 if (IS_ERR(root)) { 919 test_std_err(TEST_ALLOC_ROOT); 920 goto out; 921 } 922 923 BTRFS_I(inode)->root = root; 924 925 /* [BTRFS_MAX_EXTENT_SIZE] */ 926 ret = btrfs_set_extent_delalloc(BTRFS_I(inode), 0, 927 BTRFS_MAX_EXTENT_SIZE - 1, 0, NULL); 928 if (ret) { 929 test_err("btrfs_set_extent_delalloc returned %d", ret); 930 goto out; 931 } 932 if (BTRFS_I(inode)->outstanding_extents != 1) { 933 ret = -EINVAL; 934 test_err("miscount, wanted 1, got %u", 935 BTRFS_I(inode)->outstanding_extents); 936 goto out; 937 } 938 939 /* [BTRFS_MAX_EXTENT_SIZE][sectorsize] */ 940 ret = btrfs_set_extent_delalloc(BTRFS_I(inode), BTRFS_MAX_EXTENT_SIZE, 941 BTRFS_MAX_EXTENT_SIZE + sectorsize - 1, 942 0, NULL); 943 if (ret) { 944 test_err("btrfs_set_extent_delalloc returned %d", ret); 945 goto out; 946 } 947 if (BTRFS_I(inode)->outstanding_extents != 2) { 948 ret = -EINVAL; 949 test_err("miscount, wanted 2, got %u", 950 BTRFS_I(inode)->outstanding_extents); 951 goto out; 952 } 953 954 /* [BTRFS_MAX_EXTENT_SIZE/2][sectorsize HOLE][the rest] */ 955 ret = btrfs_clear_extent_bit(&BTRFS_I(inode)->io_tree, 956 BTRFS_MAX_EXTENT_SIZE >> 1, 957 (BTRFS_MAX_EXTENT_SIZE >> 1) + sectorsize - 1, 958 EXTENT_DELALLOC | EXTENT_DELALLOC_NEW, NULL); 959 if (ret) { 960 test_err("clear_extent_bit returned %d", ret); 961 goto out; 962 } 963 if (BTRFS_I(inode)->outstanding_extents != 2) { 964 ret = -EINVAL; 965 test_err("miscount, wanted 2, got %u", 966 BTRFS_I(inode)->outstanding_extents); 967 goto out; 968 } 969 970 /* [BTRFS_MAX_EXTENT_SIZE][sectorsize] */ 971 ret = btrfs_set_extent_delalloc(BTRFS_I(inode), BTRFS_MAX_EXTENT_SIZE >> 1, 972 (BTRFS_MAX_EXTENT_SIZE >> 1) 973 + sectorsize - 1, 974 0, NULL); 975 if (ret) { 976 test_err("btrfs_set_extent_delalloc returned %d", ret); 977 goto out; 978 } 979 if (BTRFS_I(inode)->outstanding_extents != 2) { 980 ret = -EINVAL; 981 test_err("miscount, wanted 2, got %u", 982 BTRFS_I(inode)->outstanding_extents); 983 goto out; 984 } 985 986 /* 987 * [BTRFS_MAX_EXTENT_SIZE+sectorsize][sectorsize HOLE][BTRFS_MAX_EXTENT_SIZE+sectorsize] 988 */ 989 ret = btrfs_set_extent_delalloc(BTRFS_I(inode), 990 BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize, 991 (BTRFS_MAX_EXTENT_SIZE << 1) + 3 * sectorsize - 1, 992 0, NULL); 993 if (ret) { 994 test_err("btrfs_set_extent_delalloc returned %d", ret); 995 goto out; 996 } 997 if (BTRFS_I(inode)->outstanding_extents != 4) { 998 ret = -EINVAL; 999 test_err("miscount, wanted 4, got %u", 1000 BTRFS_I(inode)->outstanding_extents); 1001 goto out; 1002 } 1003 1004 /* 1005 * [BTRFS_MAX_EXTENT_SIZE+sectorsize][sectorsize][BTRFS_MAX_EXTENT_SIZE+sectorsize] 1006 */ 1007 ret = btrfs_set_extent_delalloc(BTRFS_I(inode), 1008 BTRFS_MAX_EXTENT_SIZE + sectorsize, 1009 BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, 0, NULL); 1010 if (ret) { 1011 test_err("btrfs_set_extent_delalloc returned %d", ret); 1012 goto out; 1013 } 1014 if (BTRFS_I(inode)->outstanding_extents != 3) { 1015 ret = -EINVAL; 1016 test_err("miscount, wanted 3, got %u", 1017 BTRFS_I(inode)->outstanding_extents); 1018 goto out; 1019 } 1020 1021 /* [BTRFS_MAX_EXTENT_SIZE+4k][4K HOLE][BTRFS_MAX_EXTENT_SIZE+4k] */ 1022 ret = btrfs_clear_extent_bit(&BTRFS_I(inode)->io_tree, 1023 BTRFS_MAX_EXTENT_SIZE + sectorsize, 1024 BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, 1025 EXTENT_DELALLOC | EXTENT_DELALLOC_NEW, NULL); 1026 if (ret) { 1027 test_err("clear_extent_bit returned %d", ret); 1028 goto out; 1029 } 1030 if (BTRFS_I(inode)->outstanding_extents != 4) { 1031 ret = -EINVAL; 1032 test_err("miscount, wanted 4, got %u", 1033 BTRFS_I(inode)->outstanding_extents); 1034 goto out; 1035 } 1036 1037 /* 1038 * Refill the hole again just for good measure, because I thought it 1039 * might fail and I'd rather satisfy my paranoia at this point. 1040 */ 1041 ret = btrfs_set_extent_delalloc(BTRFS_I(inode), 1042 BTRFS_MAX_EXTENT_SIZE + sectorsize, 1043 BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, 0, NULL); 1044 if (ret) { 1045 test_err("btrfs_set_extent_delalloc returned %d", ret); 1046 goto out; 1047 } 1048 if (BTRFS_I(inode)->outstanding_extents != 3) { 1049 ret = -EINVAL; 1050 test_err("miscount, wanted 3, got %u", 1051 BTRFS_I(inode)->outstanding_extents); 1052 goto out; 1053 } 1054 1055 /* Empty */ 1056 ret = btrfs_clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, (u64)-1, 1057 EXTENT_DELALLOC | EXTENT_DELALLOC_NEW, NULL); 1058 if (ret) { 1059 test_err("clear_extent_bit returned %d", ret); 1060 goto out; 1061 } 1062 if (BTRFS_I(inode)->outstanding_extents) { 1063 ret = -EINVAL; 1064 test_err("miscount, wanted 0, got %u", 1065 BTRFS_I(inode)->outstanding_extents); 1066 goto out; 1067 } 1068 ret = 0; 1069 out: 1070 if (ret) 1071 btrfs_clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, (u64)-1, 1072 EXTENT_DELALLOC | EXTENT_DELALLOC_NEW, NULL); 1073 iput(inode); 1074 btrfs_free_dummy_root(root); 1075 btrfs_free_dummy_fs_info(fs_info); 1076 return ret; 1077 } 1078 1079 int btrfs_test_inodes(u32 sectorsize, u32 nodesize) 1080 { 1081 int ret; 1082 1083 test_msg("running inode tests"); 1084 1085 compressed_only |= EXTENT_FLAG_COMPRESS_ZLIB; 1086 prealloc_only |= EXTENT_FLAG_PREALLOC; 1087 1088 ret = test_btrfs_get_extent(sectorsize, nodesize); 1089 if (ret) 1090 return ret; 1091 ret = test_hole_first(sectorsize, nodesize); 1092 if (ret) 1093 return ret; 1094 return test_extent_accounting(sectorsize, nodesize); 1095 } 1096