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