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 - 1, 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 u32 prealloc_only = 0; 215 static u32 compressed_only = 0; 216 static u32 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, 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->disk_bytenr != EXTENT_MAP_HOLE) { 268 test_err("expected a hole, got %llu", em->disk_bytenr); 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, (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->disk_bytenr != EXTENT_MAP_INLINE) { 287 test_err("expected an inline, got %llu", em->disk_bytenr); 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 %u", 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, 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->disk_bytenr != EXTENT_MAP_HOLE) { 325 test_err("expected a hole, got %llu", em->disk_bytenr); 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 %u", 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, 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->disk_bytenr >= EXTENT_MAP_LAST_BYTE) { 348 test_err("expected a real extent, got %llu", em->disk_bytenr); 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 %u", em->flags); 359 goto out; 360 } 361 if (em->offset != 0) { 362 test_err("wrong offset, want 0, have %llu", em->offset); 363 goto out; 364 } 365 offset = em->start + em->len; 366 free_extent_map(em); 367 368 /* The next 3 are split extents */ 369 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize); 370 if (IS_ERR(em)) { 371 test_err("got an error when we shouldn't have"); 372 goto out; 373 } 374 if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) { 375 test_err("expected a real extent, got %llu", em->disk_bytenr); 376 goto out; 377 } 378 if (em->start != offset || em->len != sectorsize) { 379 test_err( 380 "unexpected extent start %llu len %u, got start %llu len %llu", 381 offset, sectorsize, em->start, em->len); 382 goto out; 383 } 384 if (em->flags != 0) { 385 test_err("unexpected flags set, want 0 have %u", em->flags); 386 goto out; 387 } 388 if (em->offset != 0) { 389 test_err("wrong offset, want 0, have %llu", em->offset); 390 goto out; 391 } 392 disk_bytenr = extent_map_block_start(em); 393 orig_start = em->start; 394 offset = em->start + em->len; 395 free_extent_map(em); 396 397 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize); 398 if (IS_ERR(em)) { 399 test_err("got an error when we shouldn't have"); 400 goto out; 401 } 402 if (em->disk_bytenr != EXTENT_MAP_HOLE) { 403 test_err("expected a hole, got %llu", em->disk_bytenr); 404 goto out; 405 } 406 if (em->start != offset || em->len != sectorsize) { 407 test_err( 408 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 409 offset, sectorsize, em->start, em->len); 410 goto out; 411 } 412 if (em->flags != 0) { 413 test_err("unexpected flags set, want 0 have %u", em->flags); 414 goto out; 415 } 416 offset = em->start + em->len; 417 free_extent_map(em); 418 419 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize); 420 if (IS_ERR(em)) { 421 test_err("got an error when we shouldn't have"); 422 goto out; 423 } 424 if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) { 425 test_err("expected a real extent, got %llu", em->disk_bytenr); 426 goto out; 427 } 428 if (em->start != offset || em->len != 2 * sectorsize) { 429 test_err( 430 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 431 offset, 2 * sectorsize, em->start, em->len); 432 goto out; 433 } 434 if (em->flags != 0) { 435 test_err("unexpected flags set, want 0 have %u", em->flags); 436 goto out; 437 } 438 if (em->start - em->offset != orig_start) { 439 test_err("wrong offset, em->start=%llu em->offset=%llu orig_start=%llu", 440 em->start, em->offset, orig_start); 441 goto out; 442 } 443 disk_bytenr += (em->start - orig_start); 444 if (extent_map_block_start(em) != disk_bytenr) { 445 test_err("wrong block start, want %llu, have %llu", 446 disk_bytenr, extent_map_block_start(em)); 447 goto out; 448 } 449 offset = em->start + em->len; 450 free_extent_map(em); 451 452 /* Prealloc extent */ 453 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize); 454 if (IS_ERR(em)) { 455 test_err("got an error when we shouldn't have"); 456 goto out; 457 } 458 if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) { 459 test_err("expected a real extent, got %llu", em->disk_bytenr); 460 goto out; 461 } 462 if (em->start != offset || em->len != sectorsize) { 463 test_err( 464 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 465 offset, sectorsize, em->start, em->len); 466 goto out; 467 } 468 if (em->flags != prealloc_only) { 469 test_err("unexpected flags set, want %u have %u", 470 prealloc_only, em->flags); 471 goto out; 472 } 473 if (em->offset != 0) { 474 test_err("wrong offset, want 0, have %llu", em->offset); 475 goto out; 476 } 477 offset = em->start + em->len; 478 free_extent_map(em); 479 480 /* The next 3 are a half written prealloc extent */ 481 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize); 482 if (IS_ERR(em)) { 483 test_err("got an error when we shouldn't have"); 484 goto out; 485 } 486 if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) { 487 test_err("expected a real extent, got %llu", em->disk_bytenr); 488 goto out; 489 } 490 if (em->start != offset || em->len != sectorsize) { 491 test_err( 492 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 493 offset, sectorsize, em->start, em->len); 494 goto out; 495 } 496 if (em->flags != prealloc_only) { 497 test_err("unexpected flags set, want %u have %u", 498 prealloc_only, em->flags); 499 goto out; 500 } 501 if (em->offset != 0) { 502 test_err("wrong offset, want 0, have %llu", em->offset); 503 goto out; 504 } 505 disk_bytenr = extent_map_block_start(em); 506 orig_start = em->start; 507 offset = em->start + em->len; 508 free_extent_map(em); 509 510 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize); 511 if (IS_ERR(em)) { 512 test_err("got an error when we shouldn't have"); 513 goto out; 514 } 515 if (em->disk_bytenr >= EXTENT_MAP_HOLE) { 516 test_err("expected a real extent, got %llu", em->disk_bytenr); 517 goto out; 518 } 519 if (em->start != offset || em->len != sectorsize) { 520 test_err( 521 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 522 offset, sectorsize, em->start, em->len); 523 goto out; 524 } 525 if (em->flags != 0) { 526 test_err("unexpected flags set, want 0 have %u", em->flags); 527 goto out; 528 } 529 if (em->start - em->offset != orig_start) { 530 test_err("unexpected offset, wanted %llu, have %llu", 531 em->start - orig_start, em->offset); 532 goto out; 533 } 534 if (extent_map_block_start(em) != disk_bytenr + em->offset) { 535 test_err("unexpected block start, wanted %llu, have %llu", 536 disk_bytenr + em->offset, extent_map_block_start(em)); 537 goto out; 538 } 539 offset = em->start + em->len; 540 free_extent_map(em); 541 542 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize); 543 if (IS_ERR(em)) { 544 test_err("got an error when we shouldn't have"); 545 goto out; 546 } 547 if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) { 548 test_err("expected a real extent, got %llu", em->disk_bytenr); 549 goto out; 550 } 551 if (em->start != offset || em->len != 2 * sectorsize) { 552 test_err( 553 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 554 offset, 2 * sectorsize, em->start, em->len); 555 goto out; 556 } 557 if (em->flags != prealloc_only) { 558 test_err("unexpected flags set, want %u have %u", 559 prealloc_only, em->flags); 560 goto out; 561 } 562 if (em->start - em->offset != orig_start) { 563 test_err("wrong offset, em->start=%llu em->offset=%llu orig_start=%llu", 564 em->start, em->offset, orig_start); 565 goto out; 566 } 567 if (extent_map_block_start(em) != disk_bytenr + em->offset) { 568 test_err("unexpected block start, wanted %llu, have %llu", 569 disk_bytenr + em->offset, extent_map_block_start(em)); 570 goto out; 571 } 572 offset = em->start + em->len; 573 free_extent_map(em); 574 575 /* Now for the compressed extent */ 576 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize); 577 if (IS_ERR(em)) { 578 test_err("got an error when we shouldn't have"); 579 goto out; 580 } 581 if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) { 582 test_err("expected a real extent, got %llu", em->disk_bytenr); 583 goto out; 584 } 585 if (em->start != offset || em->len != 2 * sectorsize) { 586 test_err( 587 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 588 offset, 2 * sectorsize, em->start, em->len); 589 goto out; 590 } 591 if (em->flags != compressed_only) { 592 test_err("unexpected flags set, want %u have %u", 593 compressed_only, em->flags); 594 goto out; 595 } 596 if (em->offset != 0) { 597 test_err("wrong offset, want 0, have %llu", em->offset); 598 goto out; 599 } 600 if (extent_map_compression(em) != BTRFS_COMPRESS_ZLIB) { 601 test_err("unexpected compress type, wanted %d, got %d", 602 BTRFS_COMPRESS_ZLIB, extent_map_compression(em)); 603 goto out; 604 } 605 offset = em->start + em->len; 606 free_extent_map(em); 607 608 /* Split compressed extent */ 609 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize); 610 if (IS_ERR(em)) { 611 test_err("got an error when we shouldn't have"); 612 goto out; 613 } 614 if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) { 615 test_err("expected a real extent, got %llu", em->disk_bytenr); 616 goto out; 617 } 618 if (em->start != offset || em->len != sectorsize) { 619 test_err( 620 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 621 offset, sectorsize, em->start, em->len); 622 goto out; 623 } 624 if (em->flags != compressed_only) { 625 test_err("unexpected flags set, want %u have %u", 626 compressed_only, em->flags); 627 goto out; 628 } 629 if (em->offset != 0) { 630 test_err("wrong offset, want 0, have %llu", em->offset); 631 goto out; 632 } 633 if (extent_map_compression(em) != BTRFS_COMPRESS_ZLIB) { 634 test_err("unexpected compress type, wanted %d, got %d", 635 BTRFS_COMPRESS_ZLIB, extent_map_compression(em)); 636 goto out; 637 } 638 disk_bytenr = extent_map_block_start(em); 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, 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->disk_bytenr >= EXTENT_MAP_LAST_BYTE) { 649 test_err("expected a real extent, got %llu", em->disk_bytenr); 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 %u", em->flags); 660 goto out; 661 } 662 if (em->offset != 0) { 663 test_err("wrong offset, want 0, have %llu", em->offset); 664 goto out; 665 } 666 offset = em->start + em->len; 667 free_extent_map(em); 668 669 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize); 670 if (IS_ERR(em)) { 671 test_err("got an error when we shouldn't have"); 672 goto out; 673 } 674 if (extent_map_block_start(em) != disk_bytenr) { 675 test_err("block start does not match, want %llu got %llu", 676 disk_bytenr, extent_map_block_start(em)); 677 goto out; 678 } 679 if (em->start != offset || em->len != 2 * sectorsize) { 680 test_err( 681 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 682 offset, 2 * sectorsize, em->start, em->len); 683 goto out; 684 } 685 if (em->flags != compressed_only) { 686 test_err("unexpected flags set, want %u have %u", 687 compressed_only, em->flags); 688 goto out; 689 } 690 if (em->start - em->offset != orig_start) { 691 test_err("wrong offset, em->start=%llu em->offset=%llu orig_start=%llu", 692 em->start, em->offset, orig_start); 693 goto out; 694 } 695 if (extent_map_compression(em) != BTRFS_COMPRESS_ZLIB) { 696 test_err("unexpected compress type, wanted %d, got %d", 697 BTRFS_COMPRESS_ZLIB, extent_map_compression(em)); 698 goto out; 699 } 700 offset = em->start + em->len; 701 free_extent_map(em); 702 703 /* A hole between regular extents but no hole extent */ 704 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset + 6, sectorsize); 705 if (IS_ERR(em)) { 706 test_err("got an error when we shouldn't have"); 707 goto out; 708 } 709 if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) { 710 test_err("expected a real extent, got %llu", em->disk_bytenr); 711 goto out; 712 } 713 if (em->start != offset || em->len != sectorsize) { 714 test_err( 715 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 716 offset, sectorsize, em->start, em->len); 717 goto out; 718 } 719 if (em->flags != 0) { 720 test_err("unexpected flags set, want 0 have %u", em->flags); 721 goto out; 722 } 723 if (em->offset != 0) { 724 test_err("wrong offset, want 0, have %llu", em->offset); 725 goto out; 726 } 727 offset = em->start + em->len; 728 free_extent_map(em); 729 730 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, SZ_4M); 731 if (IS_ERR(em)) { 732 test_err("got an error when we shouldn't have"); 733 goto out; 734 } 735 if (em->disk_bytenr != EXTENT_MAP_HOLE) { 736 test_err("expected a hole extent, got %llu", em->disk_bytenr); 737 goto out; 738 } 739 /* 740 * Currently we just return a length that we requested rather than the 741 * length of the actual hole, if this changes we'll have to change this 742 * test. 743 */ 744 if (em->start != offset || em->len != 3 * sectorsize) { 745 test_err( 746 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 747 offset, 3 * sectorsize, em->start, em->len); 748 goto out; 749 } 750 if (em->flags != vacancy_only) { 751 test_err("unexpected flags set, want %u have %u", 752 vacancy_only, em->flags); 753 goto out; 754 } 755 if (em->offset != 0) { 756 test_err("wrong offset, want 0, have %llu", em->offset); 757 goto out; 758 } 759 offset = em->start + em->len; 760 free_extent_map(em); 761 762 em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize); 763 if (IS_ERR(em)) { 764 test_err("got an error when we shouldn't have"); 765 goto out; 766 } 767 if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) { 768 test_err("expected a real extent, got %llu", em->disk_bytenr); 769 goto out; 770 } 771 if (em->start != offset || em->len != sectorsize) { 772 test_err( 773 "unexpected extent wanted start %llu len %u, got start %llu len %llu", 774 offset, sectorsize, em->start, em->len); 775 goto out; 776 } 777 if (em->flags != 0) { 778 test_err("unexpected flags set, want 0 have %u", em->flags); 779 goto out; 780 } 781 if (em->offset != 0) { 782 test_err("wrong orig offset, want 0, have %llu", em->offset); 783 goto out; 784 } 785 ret = 0; 786 out: 787 if (!IS_ERR(em)) 788 free_extent_map(em); 789 iput(inode); 790 btrfs_free_dummy_root(root); 791 btrfs_free_dummy_fs_info(fs_info); 792 return ret; 793 } 794 795 static int test_hole_first(u32 sectorsize, u32 nodesize) 796 { 797 struct btrfs_fs_info *fs_info = NULL; 798 struct inode *inode = NULL; 799 struct btrfs_root *root = NULL; 800 struct extent_map *em = NULL; 801 int ret = -ENOMEM; 802 803 test_msg("running hole first btrfs_get_extent test"); 804 805 inode = btrfs_new_test_inode(); 806 if (!inode) { 807 test_std_err(TEST_ALLOC_INODE); 808 return ret; 809 } 810 811 fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize); 812 if (!fs_info) { 813 test_std_err(TEST_ALLOC_FS_INFO); 814 goto out; 815 } 816 817 root = btrfs_alloc_dummy_root(fs_info); 818 if (IS_ERR(root)) { 819 test_std_err(TEST_ALLOC_ROOT); 820 goto out; 821 } 822 823 root->node = alloc_dummy_extent_buffer(fs_info, nodesize); 824 if (!root->node) { 825 test_std_err(TEST_ALLOC_ROOT); 826 goto out; 827 } 828 829 btrfs_set_header_nritems(root->node, 0); 830 btrfs_set_header_level(root->node, 0); 831 BTRFS_I(inode)->root = root; 832 ret = -EINVAL; 833 834 /* 835 * Need a blank inode item here just so we don't confuse 836 * btrfs_get_extent. 837 */ 838 insert_inode_item_key(root); 839 insert_extent(root, sectorsize, sectorsize, sectorsize, 0, sectorsize, 840 sectorsize, BTRFS_FILE_EXTENT_REG, 0, 1); 841 em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, 2 * sectorsize); 842 if (IS_ERR(em)) { 843 test_err("got an error when we shouldn't have"); 844 goto out; 845 } 846 if (em->disk_bytenr != EXTENT_MAP_HOLE) { 847 test_err("expected a hole, got %llu", em->disk_bytenr); 848 goto out; 849 } 850 if (em->start != 0 || em->len != sectorsize) { 851 test_err( 852 "unexpected extent wanted start 0 len %u, got start %llu len %llu", 853 sectorsize, em->start, em->len); 854 goto out; 855 } 856 if (em->flags != vacancy_only) { 857 test_err("wrong flags, wanted %u, have %u", vacancy_only, 858 em->flags); 859 goto out; 860 } 861 free_extent_map(em); 862 863 em = btrfs_get_extent(BTRFS_I(inode), NULL, sectorsize, 2 * sectorsize); 864 if (IS_ERR(em)) { 865 test_err("got an error when we shouldn't have"); 866 goto out; 867 } 868 if (extent_map_block_start(em) != sectorsize) { 869 test_err("expected a real extent, got %llu", extent_map_block_start(em)); 870 goto out; 871 } 872 if (em->start != sectorsize || em->len != sectorsize) { 873 test_err( 874 "unexpected extent wanted start %u len %u, got start %llu len %llu", 875 sectorsize, sectorsize, em->start, em->len); 876 goto out; 877 } 878 if (em->flags != 0) { 879 test_err("unexpected flags set, wanted 0 got %u", 880 em->flags); 881 goto out; 882 } 883 ret = 0; 884 out: 885 if (!IS_ERR(em)) 886 free_extent_map(em); 887 iput(inode); 888 btrfs_free_dummy_root(root); 889 btrfs_free_dummy_fs_info(fs_info); 890 return ret; 891 } 892 893 static int test_extent_accounting(u32 sectorsize, u32 nodesize) 894 { 895 struct btrfs_fs_info *fs_info = NULL; 896 struct inode *inode = NULL; 897 struct btrfs_root *root = NULL; 898 int ret = -ENOMEM; 899 900 test_msg("running outstanding_extents tests"); 901 902 inode = btrfs_new_test_inode(); 903 if (!inode) { 904 test_std_err(TEST_ALLOC_INODE); 905 return ret; 906 } 907 908 fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize); 909 if (!fs_info) { 910 test_std_err(TEST_ALLOC_FS_INFO); 911 goto out; 912 } 913 914 root = btrfs_alloc_dummy_root(fs_info); 915 if (IS_ERR(root)) { 916 test_std_err(TEST_ALLOC_ROOT); 917 goto out; 918 } 919 920 BTRFS_I(inode)->root = root; 921 922 /* [BTRFS_MAX_EXTENT_SIZE] */ 923 ret = btrfs_set_extent_delalloc(BTRFS_I(inode), 0, 924 BTRFS_MAX_EXTENT_SIZE - 1, 0, NULL); 925 if (ret) { 926 test_err("btrfs_set_extent_delalloc returned %d", ret); 927 goto out; 928 } 929 if (BTRFS_I(inode)->outstanding_extents != 1) { 930 ret = -EINVAL; 931 test_err("miscount, wanted 1, got %u", 932 BTRFS_I(inode)->outstanding_extents); 933 goto out; 934 } 935 936 /* [BTRFS_MAX_EXTENT_SIZE][sectorsize] */ 937 ret = btrfs_set_extent_delalloc(BTRFS_I(inode), BTRFS_MAX_EXTENT_SIZE, 938 BTRFS_MAX_EXTENT_SIZE + sectorsize - 1, 939 0, NULL); 940 if (ret) { 941 test_err("btrfs_set_extent_delalloc returned %d", ret); 942 goto out; 943 } 944 if (BTRFS_I(inode)->outstanding_extents != 2) { 945 ret = -EINVAL; 946 test_err("miscount, wanted 2, got %u", 947 BTRFS_I(inode)->outstanding_extents); 948 goto out; 949 } 950 951 /* [BTRFS_MAX_EXTENT_SIZE/2][sectorsize HOLE][the rest] */ 952 ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, 953 BTRFS_MAX_EXTENT_SIZE >> 1, 954 (BTRFS_MAX_EXTENT_SIZE >> 1) + sectorsize - 1, 955 EXTENT_DELALLOC | EXTENT_DELALLOC_NEW | 956 EXTENT_UPTODATE, NULL); 957 if (ret) { 958 test_err("clear_extent_bit returned %d", ret); 959 goto out; 960 } 961 if (BTRFS_I(inode)->outstanding_extents != 2) { 962 ret = -EINVAL; 963 test_err("miscount, wanted 2, got %u", 964 BTRFS_I(inode)->outstanding_extents); 965 goto out; 966 } 967 968 /* [BTRFS_MAX_EXTENT_SIZE][sectorsize] */ 969 ret = btrfs_set_extent_delalloc(BTRFS_I(inode), BTRFS_MAX_EXTENT_SIZE >> 1, 970 (BTRFS_MAX_EXTENT_SIZE >> 1) 971 + sectorsize - 1, 972 0, NULL); 973 if (ret) { 974 test_err("btrfs_set_extent_delalloc returned %d", ret); 975 goto out; 976 } 977 if (BTRFS_I(inode)->outstanding_extents != 2) { 978 ret = -EINVAL; 979 test_err("miscount, wanted 2, got %u", 980 BTRFS_I(inode)->outstanding_extents); 981 goto out; 982 } 983 984 /* 985 * [BTRFS_MAX_EXTENT_SIZE+sectorsize][sectorsize HOLE][BTRFS_MAX_EXTENT_SIZE+sectorsize] 986 */ 987 ret = btrfs_set_extent_delalloc(BTRFS_I(inode), 988 BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize, 989 (BTRFS_MAX_EXTENT_SIZE << 1) + 3 * sectorsize - 1, 990 0, NULL); 991 if (ret) { 992 test_err("btrfs_set_extent_delalloc returned %d", ret); 993 goto out; 994 } 995 if (BTRFS_I(inode)->outstanding_extents != 4) { 996 ret = -EINVAL; 997 test_err("miscount, wanted 4, got %u", 998 BTRFS_I(inode)->outstanding_extents); 999 goto out; 1000 } 1001 1002 /* 1003 * [BTRFS_MAX_EXTENT_SIZE+sectorsize][sectorsize][BTRFS_MAX_EXTENT_SIZE+sectorsize] 1004 */ 1005 ret = btrfs_set_extent_delalloc(BTRFS_I(inode), 1006 BTRFS_MAX_EXTENT_SIZE + sectorsize, 1007 BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, 0, NULL); 1008 if (ret) { 1009 test_err("btrfs_set_extent_delalloc returned %d", ret); 1010 goto out; 1011 } 1012 if (BTRFS_I(inode)->outstanding_extents != 3) { 1013 ret = -EINVAL; 1014 test_err("miscount, wanted 3, got %u", 1015 BTRFS_I(inode)->outstanding_extents); 1016 goto out; 1017 } 1018 1019 /* [BTRFS_MAX_EXTENT_SIZE+4k][4K HOLE][BTRFS_MAX_EXTENT_SIZE+4k] */ 1020 ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, 1021 BTRFS_MAX_EXTENT_SIZE + sectorsize, 1022 BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, 1023 EXTENT_DELALLOC | EXTENT_DELALLOC_NEW | 1024 EXTENT_UPTODATE, NULL); 1025 if (ret) { 1026 test_err("clear_extent_bit returned %d", ret); 1027 goto out; 1028 } 1029 if (BTRFS_I(inode)->outstanding_extents != 4) { 1030 ret = -EINVAL; 1031 test_err("miscount, wanted 4, got %u", 1032 BTRFS_I(inode)->outstanding_extents); 1033 goto out; 1034 } 1035 1036 /* 1037 * Refill the hole again just for good measure, because I thought it 1038 * might fail and I'd rather satisfy my paranoia at this point. 1039 */ 1040 ret = btrfs_set_extent_delalloc(BTRFS_I(inode), 1041 BTRFS_MAX_EXTENT_SIZE + sectorsize, 1042 BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, 0, NULL); 1043 if (ret) { 1044 test_err("btrfs_set_extent_delalloc returned %d", ret); 1045 goto out; 1046 } 1047 if (BTRFS_I(inode)->outstanding_extents != 3) { 1048 ret = -EINVAL; 1049 test_err("miscount, wanted 3, got %u", 1050 BTRFS_I(inode)->outstanding_extents); 1051 goto out; 1052 } 1053 1054 /* Empty */ 1055 ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, (u64)-1, 1056 EXTENT_DELALLOC | EXTENT_DELALLOC_NEW | 1057 EXTENT_UPTODATE, NULL); 1058 if (ret) { 1059 test_err("clear_extent_bit returned %d", ret); 1060 goto out; 1061 } 1062 if (BTRFS_I(inode)->outstanding_extents) { 1063 ret = -EINVAL; 1064 test_err("miscount, wanted 0, got %u", 1065 BTRFS_I(inode)->outstanding_extents); 1066 goto out; 1067 } 1068 ret = 0; 1069 out: 1070 if (ret) 1071 clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, (u64)-1, 1072 EXTENT_DELALLOC | EXTENT_DELALLOC_NEW | 1073 EXTENT_UPTODATE, NULL); 1074 iput(inode); 1075 btrfs_free_dummy_root(root); 1076 btrfs_free_dummy_fs_info(fs_info); 1077 return ret; 1078 } 1079 1080 int btrfs_test_inodes(u32 sectorsize, u32 nodesize) 1081 { 1082 int ret; 1083 1084 test_msg("running inode tests"); 1085 1086 compressed_only |= EXTENT_FLAG_COMPRESS_ZLIB; 1087 prealloc_only |= EXTENT_FLAG_PREALLOC; 1088 1089 ret = test_btrfs_get_extent(sectorsize, nodesize); 1090 if (ret) 1091 return ret; 1092 ret = test_hole_first(sectorsize, nodesize); 1093 if (ret) 1094 return ret; 1095 return test_extent_accounting(sectorsize, nodesize); 1096 } 1097
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.