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