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