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