Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 2013 Fusion IO.  All rights reserved.
0004  */
0005 
0006 #include <linux/types.h>
0007 #include "btrfs-tests.h"
0008 #include "../ctree.h"
0009 #include "../btrfs_inode.h"
0010 #include "../disk-io.h"
0011 #include "../extent_io.h"
0012 #include "../volumes.h"
0013 #include "../compression.h"
0014 
0015 static void insert_extent(struct btrfs_root *root, u64 start, u64 len,
0016               u64 ram_bytes, u64 offset, u64 disk_bytenr,
0017               u64 disk_len, u32 type, u8 compression, int slot)
0018 {
0019     struct btrfs_path path;
0020     struct btrfs_file_extent_item *fi;
0021     struct extent_buffer *leaf = root->node;
0022     struct btrfs_key key;
0023     u32 value_len = sizeof(struct btrfs_file_extent_item);
0024 
0025     if (type == BTRFS_FILE_EXTENT_INLINE)
0026         value_len += len;
0027     memset(&path, 0, sizeof(path));
0028 
0029     path.nodes[0] = leaf;
0030     path.slots[0] = slot;
0031 
0032     key.objectid = BTRFS_FIRST_FREE_OBJECTID;
0033     key.type = BTRFS_EXTENT_DATA_KEY;
0034     key.offset = start;
0035 
0036     btrfs_setup_item_for_insert(root, &path, &key, value_len);
0037     fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item);
0038     btrfs_set_file_extent_generation(leaf, fi, 1);
0039     btrfs_set_file_extent_type(leaf, fi, type);
0040     btrfs_set_file_extent_disk_bytenr(leaf, fi, disk_bytenr);
0041     btrfs_set_file_extent_disk_num_bytes(leaf, fi, disk_len);
0042     btrfs_set_file_extent_offset(leaf, fi, offset);
0043     btrfs_set_file_extent_num_bytes(leaf, fi, len);
0044     btrfs_set_file_extent_ram_bytes(leaf, fi, ram_bytes);
0045     btrfs_set_file_extent_compression(leaf, fi, compression);
0046     btrfs_set_file_extent_encryption(leaf, fi, 0);
0047     btrfs_set_file_extent_other_encoding(leaf, fi, 0);
0048 }
0049 
0050 static void insert_inode_item_key(struct btrfs_root *root)
0051 {
0052     struct btrfs_path path;
0053     struct extent_buffer *leaf = root->node;
0054     struct btrfs_key key;
0055     u32 value_len = 0;
0056 
0057     memset(&path, 0, sizeof(path));
0058 
0059     path.nodes[0] = leaf;
0060     path.slots[0] = 0;
0061 
0062     key.objectid = BTRFS_INODE_ITEM_KEY;
0063     key.type = BTRFS_INODE_ITEM_KEY;
0064     key.offset = 0;
0065 
0066     btrfs_setup_item_for_insert(root, &path, &key, value_len);
0067 }
0068 
0069 /*
0070  * Build the most complicated map of extents the earth has ever seen.  We want
0071  * this so we can test all of the corner cases of btrfs_get_extent.  Here is a
0072  * diagram of how the extents will look though this may not be possible we still
0073  * want to make sure everything acts normally (the last number is not inclusive)
0074  *
0075  * [0 - 5][5 -  6][     6 - 4096     ][ 4096 - 4100][4100 - 8195][8195 - 12291]
0076  * [hole ][inline][hole but no extent][  hole   ][   regular ][regular1 split]
0077  *
0078  * [12291 - 16387][16387 - 24579][24579 - 28675][ 28675 - 32771][32771 - 36867 ]
0079  * [    hole    ][regular1 split][   prealloc ][   prealloc1  ][prealloc1 written]
0080  *
0081  * [36867 - 45059][45059 - 53251][53251 - 57347][57347 - 61443][61443- 69635]
0082  * [  prealloc1  ][ compressed  ][ compressed1 ][    regular  ][ compressed1]
0083  *
0084  * [69635-73731][   73731 - 86019   ][86019-90115]
0085  * [  regular  ][ hole but no extent][  regular  ]
0086  */
0087 static void setup_file_extents(struct btrfs_root *root, u32 sectorsize)
0088 {
0089     int slot = 0;
0090     u64 disk_bytenr = SZ_1M;
0091     u64 offset = 0;
0092 
0093     /* First we want a hole */
0094     insert_extent(root, offset, 5, 5, 0, 0, 0, BTRFS_FILE_EXTENT_REG, 0,
0095               slot);
0096     slot++;
0097     offset += 5;
0098 
0099     /*
0100      * Now we want an inline extent, I don't think this is possible but hey
0101      * why not?  Also keep in mind if we have an inline extent it counts as
0102      * the whole first page.  If we were to expand it we would have to cow
0103      * and we wouldn't have an inline extent anymore.
0104      */
0105     insert_extent(root, offset, 1, 1, 0, 0, 0, BTRFS_FILE_EXTENT_INLINE, 0,
0106               slot);
0107     slot++;
0108     offset = sectorsize;
0109 
0110     /* Now another hole */
0111     insert_extent(root, offset, 4, 4, 0, 0, 0, BTRFS_FILE_EXTENT_REG, 0,
0112               slot);
0113     slot++;
0114     offset += 4;
0115 
0116     /* Now for a regular extent */
0117     insert_extent(root, offset, sectorsize - 1, sectorsize - 1, 0,
0118               disk_bytenr, sectorsize, BTRFS_FILE_EXTENT_REG, 0, slot);
0119     slot++;
0120     disk_bytenr += sectorsize;
0121     offset += sectorsize - 1;
0122 
0123     /*
0124      * Now for 3 extents that were split from a hole punch so we test
0125      * offsets properly.
0126      */
0127     insert_extent(root, offset, sectorsize, 4 * sectorsize, 0, disk_bytenr,
0128               4 * sectorsize, BTRFS_FILE_EXTENT_REG, 0, slot);
0129     slot++;
0130     offset += sectorsize;
0131     insert_extent(root, offset, sectorsize, sectorsize, 0, 0, 0,
0132               BTRFS_FILE_EXTENT_REG, 0, slot);
0133     slot++;
0134     offset += sectorsize;
0135     insert_extent(root, offset, 2 * sectorsize, 4 * sectorsize,
0136               2 * sectorsize, disk_bytenr, 4 * sectorsize,
0137               BTRFS_FILE_EXTENT_REG, 0, slot);
0138     slot++;
0139     offset += 2 * sectorsize;
0140     disk_bytenr += 4 * sectorsize;
0141 
0142     /* Now for a unwritten prealloc extent */
0143     insert_extent(root, offset, sectorsize, sectorsize, 0, disk_bytenr,
0144         sectorsize, BTRFS_FILE_EXTENT_PREALLOC, 0, slot);
0145     slot++;
0146     offset += sectorsize;
0147 
0148     /*
0149      * We want to jack up disk_bytenr a little more so the em stuff doesn't
0150      * merge our records.
0151      */
0152     disk_bytenr += 2 * sectorsize;
0153 
0154     /*
0155      * Now for a partially written prealloc extent, basically the same as
0156      * the hole punch example above.  Ram_bytes never changes when you mark
0157      * extents written btw.
0158      */
0159     insert_extent(root, offset, sectorsize, 4 * sectorsize, 0, disk_bytenr,
0160               4 * sectorsize, BTRFS_FILE_EXTENT_PREALLOC, 0, slot);
0161     slot++;
0162     offset += sectorsize;
0163     insert_extent(root, offset, sectorsize, 4 * sectorsize, sectorsize,
0164               disk_bytenr, 4 * sectorsize, BTRFS_FILE_EXTENT_REG, 0,
0165               slot);
0166     slot++;
0167     offset += sectorsize;
0168     insert_extent(root, offset, 2 * sectorsize, 4 * sectorsize,
0169               2 * sectorsize, disk_bytenr, 4 * sectorsize,
0170               BTRFS_FILE_EXTENT_PREALLOC, 0, slot);
0171     slot++;
0172     offset += 2 * sectorsize;
0173     disk_bytenr += 4 * sectorsize;
0174 
0175     /* Now a normal compressed extent */
0176     insert_extent(root, offset, 2 * sectorsize, 2 * sectorsize, 0,
0177               disk_bytenr, sectorsize, BTRFS_FILE_EXTENT_REG,
0178               BTRFS_COMPRESS_ZLIB, slot);
0179     slot++;
0180     offset += 2 * sectorsize;
0181     /* No merges */
0182     disk_bytenr += 2 * sectorsize;
0183 
0184     /* Now a split compressed extent */
0185     insert_extent(root, offset, sectorsize, 4 * sectorsize, 0, disk_bytenr,
0186               sectorsize, BTRFS_FILE_EXTENT_REG,
0187               BTRFS_COMPRESS_ZLIB, slot);
0188     slot++;
0189     offset += sectorsize;
0190     insert_extent(root, offset, sectorsize, sectorsize, 0,
0191               disk_bytenr + sectorsize, sectorsize,
0192               BTRFS_FILE_EXTENT_REG, 0, slot);
0193     slot++;
0194     offset += sectorsize;
0195     insert_extent(root, offset, 2 * sectorsize, 4 * sectorsize,
0196               2 * sectorsize, disk_bytenr, sectorsize,
0197               BTRFS_FILE_EXTENT_REG, BTRFS_COMPRESS_ZLIB, slot);
0198     slot++;
0199     offset += 2 * sectorsize;
0200     disk_bytenr += 2 * sectorsize;
0201 
0202     /* Now extents that have a hole but no hole extent */
0203     insert_extent(root, offset, sectorsize, sectorsize, 0, disk_bytenr,
0204               sectorsize, BTRFS_FILE_EXTENT_REG, 0, slot);
0205     slot++;
0206     offset += 4 * sectorsize;
0207     disk_bytenr += sectorsize;
0208     insert_extent(root, offset, sectorsize, sectorsize, 0, disk_bytenr,
0209               sectorsize, BTRFS_FILE_EXTENT_REG, 0, slot);
0210 }
0211 
0212 static unsigned long prealloc_only = 0;
0213 static unsigned long compressed_only = 0;
0214 static unsigned long vacancy_only = 0;
0215 
0216 static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
0217 {
0218     struct btrfs_fs_info *fs_info = NULL;
0219     struct inode *inode = NULL;
0220     struct btrfs_root *root = NULL;
0221     struct extent_map *em = NULL;
0222     u64 orig_start;
0223     u64 disk_bytenr;
0224     u64 offset;
0225     int ret = -ENOMEM;
0226 
0227     test_msg("running btrfs_get_extent tests");
0228 
0229     inode = btrfs_new_test_inode();
0230     if (!inode) {
0231         test_std_err(TEST_ALLOC_INODE);
0232         return ret;
0233     }
0234 
0235     fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize);
0236     if (!fs_info) {
0237         test_std_err(TEST_ALLOC_FS_INFO);
0238         goto out;
0239     }
0240 
0241     root = btrfs_alloc_dummy_root(fs_info);
0242     if (IS_ERR(root)) {
0243         test_std_err(TEST_ALLOC_ROOT);
0244         goto out;
0245     }
0246 
0247     root->node = alloc_dummy_extent_buffer(fs_info, nodesize);
0248     if (!root->node) {
0249         test_std_err(TEST_ALLOC_ROOT);
0250         goto out;
0251     }
0252 
0253     btrfs_set_header_nritems(root->node, 0);
0254     btrfs_set_header_level(root->node, 0);
0255     ret = -EINVAL;
0256 
0257     /* First with no extents */
0258     BTRFS_I(inode)->root = root;
0259     em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, 0, sectorsize);
0260     if (IS_ERR(em)) {
0261         em = NULL;
0262         test_err("got an error when we shouldn't have");
0263         goto out;
0264     }
0265     if (em->block_start != EXTENT_MAP_HOLE) {
0266         test_err("expected a hole, got %llu", em->block_start);
0267         goto out;
0268     }
0269     free_extent_map(em);
0270     btrfs_drop_extent_cache(BTRFS_I(inode), 0, (u64)-1, 0);
0271 
0272     /*
0273      * All of the magic numbers are based on the mapping setup in
0274      * setup_file_extents, so if you change anything there you need to
0275      * update the comment and update the expected values below.
0276      */
0277     setup_file_extents(root, sectorsize);
0278 
0279     em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, 0, (u64)-1);
0280     if (IS_ERR(em)) {
0281         test_err("got an error when we shouldn't have");
0282         goto out;
0283     }
0284     if (em->block_start != EXTENT_MAP_HOLE) {
0285         test_err("expected a hole, got %llu", em->block_start);
0286         goto out;
0287     }
0288     if (em->start != 0 || em->len != 5) {
0289         test_err(
0290         "unexpected extent wanted start 0 len 5, got start %llu len %llu",
0291             em->start, em->len);
0292         goto out;
0293     }
0294     if (em->flags != 0) {
0295         test_err("unexpected flags set, want 0 have %lu", em->flags);
0296         goto out;
0297     }
0298     offset = em->start + em->len;
0299     free_extent_map(em);
0300 
0301     em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
0302     if (IS_ERR(em)) {
0303         test_err("got an error when we shouldn't have");
0304         goto out;
0305     }
0306     if (em->block_start != EXTENT_MAP_INLINE) {
0307         test_err("expected an inline, got %llu", em->block_start);
0308         goto out;
0309     }
0310 
0311     if (em->start != offset || em->len != (sectorsize - 5)) {
0312         test_err(
0313     "unexpected extent wanted start %llu len 1, got start %llu len %llu",
0314             offset, em->start, em->len);
0315         goto out;
0316     }
0317     if (em->flags != 0) {
0318         test_err("unexpected flags set, want 0 have %lu", em->flags);
0319         goto out;
0320     }
0321     /*
0322      * We don't test anything else for inline since it doesn't get set
0323      * unless we have a page for it to write into.  Maybe we should change
0324      * this?
0325      */
0326     offset = em->start + em->len;
0327     free_extent_map(em);
0328 
0329     em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
0330     if (IS_ERR(em)) {
0331         test_err("got an error when we shouldn't have");
0332         goto out;
0333     }
0334     if (em->block_start != EXTENT_MAP_HOLE) {
0335         test_err("expected a hole, got %llu", em->block_start);
0336         goto out;
0337     }
0338     if (em->start != offset || em->len != 4) {
0339         test_err(
0340     "unexpected extent wanted start %llu len 4, got start %llu len %llu",
0341             offset, em->start, em->len);
0342         goto out;
0343     }
0344     if (em->flags != 0) {
0345         test_err("unexpected flags set, want 0 have %lu", em->flags);
0346         goto out;
0347     }
0348     offset = em->start + em->len;
0349     free_extent_map(em);
0350 
0351     /* Regular extent */
0352     em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
0353     if (IS_ERR(em)) {
0354         test_err("got an error when we shouldn't have");
0355         goto out;
0356     }
0357     if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
0358         test_err("expected a real extent, got %llu", em->block_start);
0359         goto out;
0360     }
0361     if (em->start != offset || em->len != sectorsize - 1) {
0362         test_err(
0363     "unexpected extent wanted start %llu len 4095, got start %llu len %llu",
0364             offset, em->start, em->len);
0365         goto out;
0366     }
0367     if (em->flags != 0) {
0368         test_err("unexpected flags set, want 0 have %lu", em->flags);
0369         goto out;
0370     }
0371     if (em->orig_start != em->start) {
0372         test_err("wrong orig offset, want %llu, have %llu", em->start,
0373              em->orig_start);
0374         goto out;
0375     }
0376     offset = em->start + em->len;
0377     free_extent_map(em);
0378 
0379     /* The next 3 are split extents */
0380     em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
0381     if (IS_ERR(em)) {
0382         test_err("got an error when we shouldn't have");
0383         goto out;
0384     }
0385     if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
0386         test_err("expected a real extent, got %llu", em->block_start);
0387         goto out;
0388     }
0389     if (em->start != offset || em->len != sectorsize) {
0390         test_err(
0391         "unexpected extent start %llu len %u, got start %llu len %llu",
0392             offset, sectorsize, em->start, em->len);
0393         goto out;
0394     }
0395     if (em->flags != 0) {
0396         test_err("unexpected flags set, want 0 have %lu", em->flags);
0397         goto out;
0398     }
0399     if (em->orig_start != em->start) {
0400         test_err("wrong orig offset, want %llu, have %llu", em->start,
0401              em->orig_start);
0402         goto out;
0403     }
0404     disk_bytenr = em->block_start;
0405     orig_start = em->start;
0406     offset = em->start + em->len;
0407     free_extent_map(em);
0408 
0409     em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
0410     if (IS_ERR(em)) {
0411         test_err("got an error when we shouldn't have");
0412         goto out;
0413     }
0414     if (em->block_start != EXTENT_MAP_HOLE) {
0415         test_err("expected a hole, got %llu", em->block_start);
0416         goto out;
0417     }
0418     if (em->start != offset || em->len != sectorsize) {
0419         test_err(
0420     "unexpected extent wanted start %llu len %u, got start %llu len %llu",
0421             offset, sectorsize, em->start, em->len);
0422         goto out;
0423     }
0424     if (em->flags != 0) {
0425         test_err("unexpected flags set, want 0 have %lu", em->flags);
0426         goto out;
0427     }
0428     offset = em->start + em->len;
0429     free_extent_map(em);
0430 
0431     em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
0432     if (IS_ERR(em)) {
0433         test_err("got an error when we shouldn't have");
0434         goto out;
0435     }
0436     if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
0437         test_err("expected a real extent, got %llu", em->block_start);
0438         goto out;
0439     }
0440     if (em->start != offset || em->len != 2 * sectorsize) {
0441         test_err(
0442     "unexpected extent wanted start %llu len %u, got start %llu len %llu",
0443             offset, 2 * sectorsize, em->start, em->len);
0444         goto out;
0445     }
0446     if (em->flags != 0) {
0447         test_err("unexpected flags set, want 0 have %lu", em->flags);
0448         goto out;
0449     }
0450     if (em->orig_start != orig_start) {
0451         test_err("wrong orig offset, want %llu, have %llu",
0452              orig_start, em->orig_start);
0453         goto out;
0454     }
0455     disk_bytenr += (em->start - orig_start);
0456     if (em->block_start != disk_bytenr) {
0457         test_err("wrong block start, want %llu, have %llu",
0458              disk_bytenr, em->block_start);
0459         goto out;
0460     }
0461     offset = em->start + em->len;
0462     free_extent_map(em);
0463 
0464     /* Prealloc extent */
0465     em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
0466     if (IS_ERR(em)) {
0467         test_err("got an error when we shouldn't have");
0468         goto out;
0469     }
0470     if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
0471         test_err("expected a real extent, got %llu", em->block_start);
0472         goto out;
0473     }
0474     if (em->start != offset || em->len != sectorsize) {
0475         test_err(
0476     "unexpected extent wanted start %llu len %u, got start %llu len %llu",
0477             offset, sectorsize, em->start, em->len);
0478         goto out;
0479     }
0480     if (em->flags != prealloc_only) {
0481         test_err("unexpected flags set, want %lu have %lu",
0482              prealloc_only, em->flags);
0483         goto out;
0484     }
0485     if (em->orig_start != em->start) {
0486         test_err("wrong orig offset, want %llu, have %llu", em->start,
0487              em->orig_start);
0488         goto out;
0489     }
0490     offset = em->start + em->len;
0491     free_extent_map(em);
0492 
0493     /* The next 3 are a half written prealloc extent */
0494     em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
0495     if (IS_ERR(em)) {
0496         test_err("got an error when we shouldn't have");
0497         goto out;
0498     }
0499     if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
0500         test_err("expected a real extent, got %llu", em->block_start);
0501         goto out;
0502     }
0503     if (em->start != offset || em->len != sectorsize) {
0504         test_err(
0505     "unexpected extent wanted start %llu len %u, got start %llu len %llu",
0506             offset, sectorsize, em->start, em->len);
0507         goto out;
0508     }
0509     if (em->flags != prealloc_only) {
0510         test_err("unexpected flags set, want %lu have %lu",
0511              prealloc_only, em->flags);
0512         goto out;
0513     }
0514     if (em->orig_start != em->start) {
0515         test_err("wrong orig offset, want %llu, have %llu", em->start,
0516              em->orig_start);
0517         goto out;
0518     }
0519     disk_bytenr = em->block_start;
0520     orig_start = em->start;
0521     offset = em->start + em->len;
0522     free_extent_map(em);
0523 
0524     em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
0525     if (IS_ERR(em)) {
0526         test_err("got an error when we shouldn't have");
0527         goto out;
0528     }
0529     if (em->block_start >= EXTENT_MAP_HOLE) {
0530         test_err("expected a real extent, got %llu", em->block_start);
0531         goto out;
0532     }
0533     if (em->start != offset || em->len != sectorsize) {
0534         test_err(
0535     "unexpected extent wanted start %llu len %u, got start %llu len %llu",
0536             offset, sectorsize, em->start, em->len);
0537         goto out;
0538     }
0539     if (em->flags != 0) {
0540         test_err("unexpected flags set, want 0 have %lu", em->flags);
0541         goto out;
0542     }
0543     if (em->orig_start != orig_start) {
0544         test_err("unexpected orig offset, wanted %llu, have %llu",
0545              orig_start, em->orig_start);
0546         goto out;
0547     }
0548     if (em->block_start != (disk_bytenr + (em->start - em->orig_start))) {
0549         test_err("unexpected block start, wanted %llu, have %llu",
0550              disk_bytenr + (em->start - em->orig_start),
0551              em->block_start);
0552         goto out;
0553     }
0554     offset = em->start + em->len;
0555     free_extent_map(em);
0556 
0557     em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
0558     if (IS_ERR(em)) {
0559         test_err("got an error when we shouldn't have");
0560         goto out;
0561     }
0562     if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
0563         test_err("expected a real extent, got %llu", em->block_start);
0564         goto out;
0565     }
0566     if (em->start != offset || em->len != 2 * sectorsize) {
0567         test_err(
0568     "unexpected extent wanted start %llu len %u, got start %llu len %llu",
0569             offset, 2 * sectorsize, em->start, em->len);
0570         goto out;
0571     }
0572     if (em->flags != prealloc_only) {
0573         test_err("unexpected flags set, want %lu have %lu",
0574              prealloc_only, em->flags);
0575         goto out;
0576     }
0577     if (em->orig_start != orig_start) {
0578         test_err("wrong orig offset, want %llu, have %llu", orig_start,
0579              em->orig_start);
0580         goto out;
0581     }
0582     if (em->block_start != (disk_bytenr + (em->start - em->orig_start))) {
0583         test_err("unexpected block start, wanted %llu, have %llu",
0584              disk_bytenr + (em->start - em->orig_start),
0585              em->block_start);
0586         goto out;
0587     }
0588     offset = em->start + em->len;
0589     free_extent_map(em);
0590 
0591     /* Now for the compressed extent */
0592     em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
0593     if (IS_ERR(em)) {
0594         test_err("got an error when we shouldn't have");
0595         goto out;
0596     }
0597     if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
0598         test_err("expected a real extent, got %llu", em->block_start);
0599         goto out;
0600     }
0601     if (em->start != offset || em->len != 2 * sectorsize) {
0602         test_err(
0603     "unexpected extent wanted start %llu len %u, got start %llu len %llu",
0604             offset, 2 * sectorsize, em->start, em->len);
0605         goto out;
0606     }
0607     if (em->flags != compressed_only) {
0608         test_err("unexpected flags set, want %lu have %lu",
0609              compressed_only, em->flags);
0610         goto out;
0611     }
0612     if (em->orig_start != em->start) {
0613         test_err("wrong orig offset, want %llu, have %llu",
0614              em->start, em->orig_start);
0615         goto out;
0616     }
0617     if (em->compress_type != BTRFS_COMPRESS_ZLIB) {
0618         test_err("unexpected compress type, wanted %d, got %d",
0619              BTRFS_COMPRESS_ZLIB, em->compress_type);
0620         goto out;
0621     }
0622     offset = em->start + em->len;
0623     free_extent_map(em);
0624 
0625     /* Split compressed extent */
0626     em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
0627     if (IS_ERR(em)) {
0628         test_err("got an error when we shouldn't have");
0629         goto out;
0630     }
0631     if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
0632         test_err("expected a real extent, got %llu", em->block_start);
0633         goto out;
0634     }
0635     if (em->start != offset || em->len != sectorsize) {
0636         test_err(
0637     "unexpected extent wanted start %llu len %u, got start %llu len %llu",
0638             offset, sectorsize, em->start, em->len);
0639         goto out;
0640     }
0641     if (em->flags != compressed_only) {
0642         test_err("unexpected flags set, want %lu have %lu",
0643              compressed_only, em->flags);
0644         goto out;
0645     }
0646     if (em->orig_start != em->start) {
0647         test_err("wrong orig offset, want %llu, have %llu",
0648              em->start, em->orig_start);
0649         goto out;
0650     }
0651     if (em->compress_type != BTRFS_COMPRESS_ZLIB) {
0652         test_err("unexpected compress type, wanted %d, got %d",
0653              BTRFS_COMPRESS_ZLIB, em->compress_type);
0654         goto out;
0655     }
0656     disk_bytenr = em->block_start;
0657     orig_start = em->start;
0658     offset = em->start + em->len;
0659     free_extent_map(em);
0660 
0661     em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
0662     if (IS_ERR(em)) {
0663         test_err("got an error when we shouldn't have");
0664         goto out;
0665     }
0666     if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
0667         test_err("expected a real extent, got %llu", em->block_start);
0668         goto out;
0669     }
0670     if (em->start != offset || em->len != sectorsize) {
0671         test_err(
0672     "unexpected extent wanted start %llu len %u, got start %llu len %llu",
0673             offset, sectorsize, em->start, em->len);
0674         goto out;
0675     }
0676     if (em->flags != 0) {
0677         test_err("unexpected flags set, want 0 have %lu", em->flags);
0678         goto out;
0679     }
0680     if (em->orig_start != em->start) {
0681         test_err("wrong orig offset, want %llu, have %llu", em->start,
0682              em->orig_start);
0683         goto out;
0684     }
0685     offset = em->start + em->len;
0686     free_extent_map(em);
0687 
0688     em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
0689     if (IS_ERR(em)) {
0690         test_err("got an error when we shouldn't have");
0691         goto out;
0692     }
0693     if (em->block_start != disk_bytenr) {
0694         test_err("block start does not match, want %llu got %llu",
0695              disk_bytenr, em->block_start);
0696         goto out;
0697     }
0698     if (em->start != offset || em->len != 2 * sectorsize) {
0699         test_err(
0700     "unexpected extent wanted start %llu len %u, got start %llu len %llu",
0701             offset, 2 * sectorsize, em->start, em->len);
0702         goto out;
0703     }
0704     if (em->flags != compressed_only) {
0705         test_err("unexpected flags set, want %lu have %lu",
0706              compressed_only, em->flags);
0707         goto out;
0708     }
0709     if (em->orig_start != orig_start) {
0710         test_err("wrong orig offset, want %llu, have %llu",
0711              em->start, orig_start);
0712         goto out;
0713     }
0714     if (em->compress_type != BTRFS_COMPRESS_ZLIB) {
0715         test_err("unexpected compress type, wanted %d, got %d",
0716              BTRFS_COMPRESS_ZLIB, em->compress_type);
0717         goto out;
0718     }
0719     offset = em->start + em->len;
0720     free_extent_map(em);
0721 
0722     /* A hole between regular extents but no hole extent */
0723     em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset + 6, sectorsize);
0724     if (IS_ERR(em)) {
0725         test_err("got an error when we shouldn't have");
0726         goto out;
0727     }
0728     if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
0729         test_err("expected a real extent, got %llu", em->block_start);
0730         goto out;
0731     }
0732     if (em->start != offset || em->len != sectorsize) {
0733         test_err(
0734     "unexpected extent wanted start %llu len %u, got start %llu len %llu",
0735             offset, sectorsize, em->start, em->len);
0736         goto out;
0737     }
0738     if (em->flags != 0) {
0739         test_err("unexpected flags set, want 0 have %lu", em->flags);
0740         goto out;
0741     }
0742     if (em->orig_start != em->start) {
0743         test_err("wrong orig offset, want %llu, have %llu", em->start,
0744              em->orig_start);
0745         goto out;
0746     }
0747     offset = em->start + em->len;
0748     free_extent_map(em);
0749 
0750     em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, SZ_4M);
0751     if (IS_ERR(em)) {
0752         test_err("got an error when we shouldn't have");
0753         goto out;
0754     }
0755     if (em->block_start != EXTENT_MAP_HOLE) {
0756         test_err("expected a hole extent, got %llu", em->block_start);
0757         goto out;
0758     }
0759     /*
0760      * Currently we just return a length that we requested rather than the
0761      * length of the actual hole, if this changes we'll have to change this
0762      * test.
0763      */
0764     if (em->start != offset || em->len != 3 * sectorsize) {
0765         test_err(
0766     "unexpected extent wanted start %llu len %u, got start %llu len %llu",
0767             offset, 3 * sectorsize, em->start, em->len);
0768         goto out;
0769     }
0770     if (em->flags != vacancy_only) {
0771         test_err("unexpected flags set, want %lu have %lu",
0772              vacancy_only, em->flags);
0773         goto out;
0774     }
0775     if (em->orig_start != em->start) {
0776         test_err("wrong orig offset, want %llu, have %llu", em->start,
0777              em->orig_start);
0778         goto out;
0779     }
0780     offset = em->start + em->len;
0781     free_extent_map(em);
0782 
0783     em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
0784     if (IS_ERR(em)) {
0785         test_err("got an error when we shouldn't have");
0786         goto out;
0787     }
0788     if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
0789         test_err("expected a real extent, got %llu", em->block_start);
0790         goto out;
0791     }
0792     if (em->start != offset || em->len != sectorsize) {
0793         test_err(
0794     "unexpected extent wanted start %llu len %u, got start %llu len %llu",
0795             offset, sectorsize, em->start, em->len);
0796         goto out;
0797     }
0798     if (em->flags != 0) {
0799         test_err("unexpected flags set, want 0 have %lu", em->flags);
0800         goto out;
0801     }
0802     if (em->orig_start != em->start) {
0803         test_err("wrong orig offset, want %llu, have %llu", em->start,
0804              em->orig_start);
0805         goto out;
0806     }
0807     ret = 0;
0808 out:
0809     if (!IS_ERR(em))
0810         free_extent_map(em);
0811     iput(inode);
0812     btrfs_free_dummy_root(root);
0813     btrfs_free_dummy_fs_info(fs_info);
0814     return ret;
0815 }
0816 
0817 static int test_hole_first(u32 sectorsize, u32 nodesize)
0818 {
0819     struct btrfs_fs_info *fs_info = NULL;
0820     struct inode *inode = NULL;
0821     struct btrfs_root *root = NULL;
0822     struct extent_map *em = NULL;
0823     int ret = -ENOMEM;
0824 
0825     test_msg("running hole first btrfs_get_extent test");
0826 
0827     inode = btrfs_new_test_inode();
0828     if (!inode) {
0829         test_std_err(TEST_ALLOC_INODE);
0830         return ret;
0831     }
0832 
0833     fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize);
0834     if (!fs_info) {
0835         test_std_err(TEST_ALLOC_FS_INFO);
0836         goto out;
0837     }
0838 
0839     root = btrfs_alloc_dummy_root(fs_info);
0840     if (IS_ERR(root)) {
0841         test_std_err(TEST_ALLOC_ROOT);
0842         goto out;
0843     }
0844 
0845     root->node = alloc_dummy_extent_buffer(fs_info, nodesize);
0846     if (!root->node) {
0847         test_std_err(TEST_ALLOC_ROOT);
0848         goto out;
0849     }
0850 
0851     btrfs_set_header_nritems(root->node, 0);
0852     btrfs_set_header_level(root->node, 0);
0853     BTRFS_I(inode)->root = root;
0854     ret = -EINVAL;
0855 
0856     /*
0857      * Need a blank inode item here just so we don't confuse
0858      * btrfs_get_extent.
0859      */
0860     insert_inode_item_key(root);
0861     insert_extent(root, sectorsize, sectorsize, sectorsize, 0, sectorsize,
0862               sectorsize, BTRFS_FILE_EXTENT_REG, 0, 1);
0863     em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, 0, 2 * sectorsize);
0864     if (IS_ERR(em)) {
0865         test_err("got an error when we shouldn't have");
0866         goto out;
0867     }
0868     if (em->block_start != EXTENT_MAP_HOLE) {
0869         test_err("expected a hole, got %llu", em->block_start);
0870         goto out;
0871     }
0872     if (em->start != 0 || em->len != sectorsize) {
0873         test_err(
0874     "unexpected extent wanted start 0 len %u, got start %llu len %llu",
0875             sectorsize, em->start, em->len);
0876         goto out;
0877     }
0878     if (em->flags != vacancy_only) {
0879         test_err("wrong flags, wanted %lu, have %lu", vacancy_only,
0880              em->flags);
0881         goto out;
0882     }
0883     free_extent_map(em);
0884 
0885     em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, sectorsize, 2 * sectorsize);
0886     if (IS_ERR(em)) {
0887         test_err("got an error when we shouldn't have");
0888         goto out;
0889     }
0890     if (em->block_start != sectorsize) {
0891         test_err("expected a real extent, got %llu", em->block_start);
0892         goto out;
0893     }
0894     if (em->start != sectorsize || em->len != sectorsize) {
0895         test_err(
0896     "unexpected extent wanted start %u len %u, got start %llu len %llu",
0897             sectorsize, sectorsize, em->start, em->len);
0898         goto out;
0899     }
0900     if (em->flags != 0) {
0901         test_err("unexpected flags set, wanted 0 got %lu",
0902              em->flags);
0903         goto out;
0904     }
0905     ret = 0;
0906 out:
0907     if (!IS_ERR(em))
0908         free_extent_map(em);
0909     iput(inode);
0910     btrfs_free_dummy_root(root);
0911     btrfs_free_dummy_fs_info(fs_info);
0912     return ret;
0913 }
0914 
0915 static int test_extent_accounting(u32 sectorsize, u32 nodesize)
0916 {
0917     struct btrfs_fs_info *fs_info = NULL;
0918     struct inode *inode = NULL;
0919     struct btrfs_root *root = NULL;
0920     int ret = -ENOMEM;
0921 
0922     test_msg("running outstanding_extents tests");
0923 
0924     inode = btrfs_new_test_inode();
0925     if (!inode) {
0926         test_std_err(TEST_ALLOC_INODE);
0927         return ret;
0928     }
0929 
0930     fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize);
0931     if (!fs_info) {
0932         test_std_err(TEST_ALLOC_FS_INFO);
0933         goto out;
0934     }
0935 
0936     root = btrfs_alloc_dummy_root(fs_info);
0937     if (IS_ERR(root)) {
0938         test_std_err(TEST_ALLOC_ROOT);
0939         goto out;
0940     }
0941 
0942     BTRFS_I(inode)->root = root;
0943 
0944     /* [BTRFS_MAX_EXTENT_SIZE] */
0945     ret = btrfs_set_extent_delalloc(BTRFS_I(inode), 0,
0946                     BTRFS_MAX_EXTENT_SIZE - 1, 0, NULL);
0947     if (ret) {
0948         test_err("btrfs_set_extent_delalloc returned %d", ret);
0949         goto out;
0950     }
0951     if (BTRFS_I(inode)->outstanding_extents != 1) {
0952         ret = -EINVAL;
0953         test_err("miscount, wanted 1, got %u",
0954              BTRFS_I(inode)->outstanding_extents);
0955         goto out;
0956     }
0957 
0958     /* [BTRFS_MAX_EXTENT_SIZE][sectorsize] */
0959     ret = btrfs_set_extent_delalloc(BTRFS_I(inode), BTRFS_MAX_EXTENT_SIZE,
0960                     BTRFS_MAX_EXTENT_SIZE + sectorsize - 1,
0961                     0, NULL);
0962     if (ret) {
0963         test_err("btrfs_set_extent_delalloc returned %d", ret);
0964         goto out;
0965     }
0966     if (BTRFS_I(inode)->outstanding_extents != 2) {
0967         ret = -EINVAL;
0968         test_err("miscount, wanted 2, got %u",
0969              BTRFS_I(inode)->outstanding_extents);
0970         goto out;
0971     }
0972 
0973     /* [BTRFS_MAX_EXTENT_SIZE/2][sectorsize HOLE][the rest] */
0974     ret = clear_extent_bit(&BTRFS_I(inode)->io_tree,
0975                    BTRFS_MAX_EXTENT_SIZE >> 1,
0976                    (BTRFS_MAX_EXTENT_SIZE >> 1) + sectorsize - 1,
0977                    EXTENT_DELALLOC | EXTENT_DELALLOC_NEW |
0978                    EXTENT_UPTODATE, 0, 0, NULL);
0979     if (ret) {
0980         test_err("clear_extent_bit returned %d", ret);
0981         goto out;
0982     }
0983     if (BTRFS_I(inode)->outstanding_extents != 2) {
0984         ret = -EINVAL;
0985         test_err("miscount, wanted 2, got %u",
0986              BTRFS_I(inode)->outstanding_extents);
0987         goto out;
0988     }
0989 
0990     /* [BTRFS_MAX_EXTENT_SIZE][sectorsize] */
0991     ret = btrfs_set_extent_delalloc(BTRFS_I(inode), BTRFS_MAX_EXTENT_SIZE >> 1,
0992                     (BTRFS_MAX_EXTENT_SIZE >> 1)
0993                     + sectorsize - 1,
0994                     0, NULL);
0995     if (ret) {
0996         test_err("btrfs_set_extent_delalloc returned %d", ret);
0997         goto out;
0998     }
0999     if (BTRFS_I(inode)->outstanding_extents != 2) {
1000         ret = -EINVAL;
1001         test_err("miscount, wanted 2, got %u",
1002              BTRFS_I(inode)->outstanding_extents);
1003         goto out;
1004     }
1005 
1006     /*
1007      * [BTRFS_MAX_EXTENT_SIZE+sectorsize][sectorsize HOLE][BTRFS_MAX_EXTENT_SIZE+sectorsize]
1008      */
1009     ret = btrfs_set_extent_delalloc(BTRFS_I(inode),
1010             BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize,
1011             (BTRFS_MAX_EXTENT_SIZE << 1) + 3 * sectorsize - 1,
1012             0, NULL);
1013     if (ret) {
1014         test_err("btrfs_set_extent_delalloc returned %d", ret);
1015         goto out;
1016     }
1017     if (BTRFS_I(inode)->outstanding_extents != 4) {
1018         ret = -EINVAL;
1019         test_err("miscount, wanted 4, got %u",
1020              BTRFS_I(inode)->outstanding_extents);
1021         goto out;
1022     }
1023 
1024     /*
1025     * [BTRFS_MAX_EXTENT_SIZE+sectorsize][sectorsize][BTRFS_MAX_EXTENT_SIZE+sectorsize]
1026     */
1027     ret = btrfs_set_extent_delalloc(BTRFS_I(inode),
1028             BTRFS_MAX_EXTENT_SIZE + sectorsize,
1029             BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, 0, NULL);
1030     if (ret) {
1031         test_err("btrfs_set_extent_delalloc returned %d", ret);
1032         goto out;
1033     }
1034     if (BTRFS_I(inode)->outstanding_extents != 3) {
1035         ret = -EINVAL;
1036         test_err("miscount, wanted 3, got %u",
1037              BTRFS_I(inode)->outstanding_extents);
1038         goto out;
1039     }
1040 
1041     /* [BTRFS_MAX_EXTENT_SIZE+4k][4K HOLE][BTRFS_MAX_EXTENT_SIZE+4k] */
1042     ret = clear_extent_bit(&BTRFS_I(inode)->io_tree,
1043                    BTRFS_MAX_EXTENT_SIZE + sectorsize,
1044                    BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1,
1045                    EXTENT_DELALLOC | EXTENT_DELALLOC_NEW |
1046                    EXTENT_UPTODATE, 0, 0, NULL);
1047     if (ret) {
1048         test_err("clear_extent_bit returned %d", ret);
1049         goto out;
1050     }
1051     if (BTRFS_I(inode)->outstanding_extents != 4) {
1052         ret = -EINVAL;
1053         test_err("miscount, wanted 4, got %u",
1054              BTRFS_I(inode)->outstanding_extents);
1055         goto out;
1056     }
1057 
1058     /*
1059      * Refill the hole again just for good measure, because I thought it
1060      * might fail and I'd rather satisfy my paranoia at this point.
1061      */
1062     ret = btrfs_set_extent_delalloc(BTRFS_I(inode),
1063             BTRFS_MAX_EXTENT_SIZE + sectorsize,
1064             BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, 0, NULL);
1065     if (ret) {
1066         test_err("btrfs_set_extent_delalloc returned %d", ret);
1067         goto out;
1068     }
1069     if (BTRFS_I(inode)->outstanding_extents != 3) {
1070         ret = -EINVAL;
1071         test_err("miscount, wanted 3, got %u",
1072              BTRFS_I(inode)->outstanding_extents);
1073         goto out;
1074     }
1075 
1076     /* Empty */
1077     ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, (u64)-1,
1078                    EXTENT_DELALLOC | EXTENT_DELALLOC_NEW |
1079                    EXTENT_UPTODATE, 0, 0, NULL);
1080     if (ret) {
1081         test_err("clear_extent_bit returned %d", ret);
1082         goto out;
1083     }
1084     if (BTRFS_I(inode)->outstanding_extents) {
1085         ret = -EINVAL;
1086         test_err("miscount, wanted 0, got %u",
1087              BTRFS_I(inode)->outstanding_extents);
1088         goto out;
1089     }
1090     ret = 0;
1091 out:
1092     if (ret)
1093         clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, (u64)-1,
1094                  EXTENT_DELALLOC | EXTENT_DELALLOC_NEW |
1095                  EXTENT_UPTODATE, 0, 0, NULL);
1096     iput(inode);
1097     btrfs_free_dummy_root(root);
1098     btrfs_free_dummy_fs_info(fs_info);
1099     return ret;
1100 }
1101 
1102 int btrfs_test_inodes(u32 sectorsize, u32 nodesize)
1103 {
1104     int ret;
1105 
1106     test_msg("running inode tests");
1107 
1108     set_bit(EXTENT_FLAG_COMPRESSED, &compressed_only);
1109     set_bit(EXTENT_FLAG_PREALLOC, &prealloc_only);
1110 
1111     ret = test_btrfs_get_extent(sectorsize, nodesize);
1112     if (ret)
1113         return ret;
1114     ret = test_hole_first(sectorsize, nodesize);
1115     if (ret)
1116         return ret;
1117     return test_extent_accounting(sectorsize, nodesize);
1118 }