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