linux/fs/btrfs/tests/inode-tests.c
<<
>>
Prefs
   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