root/fs/btrfs/tests/inode-tests.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. insert_extent
  2. insert_inode_item_key
  3. setup_file_extents
  4. test_btrfs_get_extent
  5. test_hole_first
  6. test_extent_accounting
  7. btrfs_test_inodes

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

/* [<][>][^][v][top][bottom][index][help] */