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