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