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