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