GNU Linux-libre 6.8.9-gnu
[releases.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 #include "../accessors.h"
15
16 static void insert_extent(struct btrfs_root *root, u64 start, u64 len,
17                           u64 ram_bytes, u64 offset, u64 disk_bytenr,
18                           u64 disk_len, u32 type, u8 compression, int slot)
19 {
20         struct btrfs_path path;
21         struct btrfs_file_extent_item *fi;
22         struct extent_buffer *leaf = root->node;
23         struct btrfs_key key;
24         u32 value_len = sizeof(struct btrfs_file_extent_item);
25
26         if (type == BTRFS_FILE_EXTENT_INLINE)
27                 value_len += len;
28         memset(&path, 0, sizeof(path));
29
30         path.nodes[0] = leaf;
31         path.slots[0] = slot;
32
33         key.objectid = BTRFS_FIRST_FREE_OBJECTID;
34         key.type = BTRFS_EXTENT_DATA_KEY;
35         key.offset = start;
36
37         /*
38          * Passing a NULL trans handle is fine here, we have a dummy root eb
39          * and the tree is a single node (level 0).
40          */
41         btrfs_setup_item_for_insert(NULL, root, &path, &key, value_len);
42         fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item);
43         btrfs_set_file_extent_generation(leaf, fi, 1);
44         btrfs_set_file_extent_type(leaf, fi, type);
45         btrfs_set_file_extent_disk_bytenr(leaf, fi, disk_bytenr);
46         btrfs_set_file_extent_disk_num_bytes(leaf, fi, disk_len);
47         btrfs_set_file_extent_offset(leaf, fi, offset);
48         btrfs_set_file_extent_num_bytes(leaf, fi, len);
49         btrfs_set_file_extent_ram_bytes(leaf, fi, ram_bytes);
50         btrfs_set_file_extent_compression(leaf, fi, compression);
51         btrfs_set_file_extent_encryption(leaf, fi, 0);
52         btrfs_set_file_extent_other_encoding(leaf, fi, 0);
53 }
54
55 static void insert_inode_item_key(struct btrfs_root *root)
56 {
57         struct btrfs_path path;
58         struct extent_buffer *leaf = root->node;
59         struct btrfs_key key;
60         u32 value_len = 0;
61
62         memset(&path, 0, sizeof(path));
63
64         path.nodes[0] = leaf;
65         path.slots[0] = 0;
66
67         key.objectid = BTRFS_INODE_ITEM_KEY;
68         key.type = BTRFS_INODE_ITEM_KEY;
69         key.offset = 0;
70
71         /*
72          * Passing a NULL trans handle is fine here, we have a dummy root eb
73          * and the tree is a single node (level 0).
74          */
75         btrfs_setup_item_for_insert(NULL, root, &path, &key, value_len);
76 }
77
78 /*
79  * Build the most complicated map of extents the earth has ever seen.  We want
80  * this so we can test all of the corner cases of btrfs_get_extent.  Here is a
81  * diagram of how the extents will look though this may not be possible we still
82  * want to make sure everything acts normally (the last number is not inclusive)
83  *
84  * [0  - 6][     6 - 4096     ][ 4096 - 4100][4100 - 8195][8195  -  12291]
85  * [inline][hole but no extent][    hole    ][   regular ][regular1 split]
86  *
87  * [12291 - 16387][16387 - 24579][24579 - 28675][ 28675 - 32771][32771 - 36867 ]
88  * [    hole    ][regular1 split][   prealloc ][   prealloc1  ][prealloc1 written]
89  *
90  * [36867 - 45059][45059 - 53251][53251 - 57347][57347 - 61443][61443- 69635]
91  * [  prealloc1  ][ compressed  ][ compressed1 ][    regular  ][ compressed1]
92  *
93  * [69635-73731][   73731 - 86019   ][86019-90115]
94  * [  regular  ][ hole but no extent][  regular  ]
95  */
96 static void setup_file_extents(struct btrfs_root *root, u32 sectorsize)
97 {
98         int slot = 0;
99         u64 disk_bytenr = SZ_1M;
100         u64 offset = 0;
101
102         /*
103          * Tree-checker has strict limits on inline extents that they can only
104          * exist at file offset 0, thus we can only have one inline file extent
105          * at most.
106          */
107         insert_extent(root, offset, 6, 6, 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 u32 prealloc_only = 0;
215 static u32 compressed_only = 0;
216 static u32 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         fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize);
238         if (!fs_info) {
239                 test_std_err(TEST_ALLOC_FS_INFO);
240                 goto out;
241         }
242
243         root = btrfs_alloc_dummy_root(fs_info);
244         if (IS_ERR(root)) {
245                 test_std_err(TEST_ALLOC_ROOT);
246                 goto out;
247         }
248
249         root->node = alloc_dummy_extent_buffer(fs_info, nodesize);
250         if (!root->node) {
251                 test_std_err(TEST_ALLOC_ROOT);
252                 goto out;
253         }
254
255         btrfs_set_header_nritems(root->node, 0);
256         btrfs_set_header_level(root->node, 0);
257         ret = -EINVAL;
258
259         /* First with no extents */
260         BTRFS_I(inode)->root = root;
261         em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, 0, sectorsize);
262         if (IS_ERR(em)) {
263                 em = NULL;
264                 test_err("got an error when we shouldn't have");
265                 goto out;
266         }
267         if (em->block_start != EXTENT_MAP_HOLE) {
268                 test_err("expected a hole, got %llu", em->block_start);
269                 goto out;
270         }
271         free_extent_map(em);
272         btrfs_drop_extent_map_range(BTRFS_I(inode), 0, (u64)-1, false);
273
274         /*
275          * All of the magic numbers are based on the mapping setup in
276          * setup_file_extents, so if you change anything there you need to
277          * update the comment and update the expected values below.
278          */
279         setup_file_extents(root, sectorsize);
280
281         em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, 0, (u64)-1);
282         if (IS_ERR(em)) {
283                 test_err("got an error when we shouldn't have");
284                 goto out;
285         }
286         if (em->block_start != EXTENT_MAP_INLINE) {
287                 test_err("expected an inline, got %llu", em->block_start);
288                 goto out;
289         }
290
291         /*
292          * For inline extent, we always round up the em to sectorsize, as
293          * they are either:
294          *
295          * a) a hidden hole
296          *    The range will be zeroed at inline extent read time.
297          *
298          * b) a file extent with unaligned bytenr
299          *    Tree checker will reject it.
300          */
301         if (em->start != 0 || em->len != sectorsize) {
302                 test_err(
303         "unexpected extent wanted start 0 len %u, got start %llu len %llu",
304                         sectorsize, em->start, em->len);
305                 goto out;
306         }
307         if (em->flags != 0) {
308                 test_err("unexpected flags set, want 0 have %u", em->flags);
309                 goto out;
310         }
311         /*
312          * We don't test anything else for inline since it doesn't get set
313          * unless we have a page for it to write into.  Maybe we should change
314          * this?
315          */
316         offset = em->start + em->len;
317         free_extent_map(em);
318
319         em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
320         if (IS_ERR(em)) {
321                 test_err("got an error when we shouldn't have");
322                 goto out;
323         }
324         if (em->block_start != EXTENT_MAP_HOLE) {
325                 test_err("expected a hole, got %llu", em->block_start);
326                 goto out;
327         }
328         if (em->start != offset || em->len != 4) {
329                 test_err(
330         "unexpected extent wanted start %llu len 4, got start %llu len %llu",
331                         offset, em->start, em->len);
332                 goto out;
333         }
334         if (em->flags != 0) {
335                 test_err("unexpected flags set, want 0 have %u", em->flags);
336                 goto out;
337         }
338         offset = em->start + em->len;
339         free_extent_map(em);
340
341         /* Regular extent */
342         em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
343         if (IS_ERR(em)) {
344                 test_err("got an error when we shouldn't have");
345                 goto out;
346         }
347         if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
348                 test_err("expected a real extent, got %llu", em->block_start);
349                 goto out;
350         }
351         if (em->start != offset || em->len != sectorsize - 1) {
352                 test_err(
353         "unexpected extent wanted start %llu len 4095, got start %llu len %llu",
354                         offset, em->start, em->len);
355                 goto out;
356         }
357         if (em->flags != 0) {
358                 test_err("unexpected flags set, want 0 have %u", em->flags);
359                 goto out;
360         }
361         if (em->orig_start != em->start) {
362                 test_err("wrong orig offset, want %llu, have %llu", em->start,
363                          em->orig_start);
364                 goto out;
365         }
366         offset = em->start + em->len;
367         free_extent_map(em);
368
369         /* The next 3 are split extents */
370         em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
371         if (IS_ERR(em)) {
372                 test_err("got an error when we shouldn't have");
373                 goto out;
374         }
375         if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
376                 test_err("expected a real extent, got %llu", em->block_start);
377                 goto out;
378         }
379         if (em->start != offset || em->len != sectorsize) {
380                 test_err(
381                 "unexpected extent start %llu len %u, got start %llu len %llu",
382                         offset, sectorsize, em->start, em->len);
383                 goto out;
384         }
385         if (em->flags != 0) {
386                 test_err("unexpected flags set, want 0 have %u", em->flags);
387                 goto out;
388         }
389         if (em->orig_start != em->start) {
390                 test_err("wrong orig offset, want %llu, have %llu", em->start,
391                          em->orig_start);
392                 goto out;
393         }
394         disk_bytenr = em->block_start;
395         orig_start = em->start;
396         offset = em->start + em->len;
397         free_extent_map(em);
398
399         em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
400         if (IS_ERR(em)) {
401                 test_err("got an error when we shouldn't have");
402                 goto out;
403         }
404         if (em->block_start != EXTENT_MAP_HOLE) {
405                 test_err("expected a hole, got %llu", em->block_start);
406                 goto out;
407         }
408         if (em->start != offset || em->len != sectorsize) {
409                 test_err(
410         "unexpected extent wanted start %llu len %u, got start %llu len %llu",
411                         offset, sectorsize, em->start, em->len);
412                 goto out;
413         }
414         if (em->flags != 0) {
415                 test_err("unexpected flags set, want 0 have %u", em->flags);
416                 goto out;
417         }
418         offset = em->start + em->len;
419         free_extent_map(em);
420
421         em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
422         if (IS_ERR(em)) {
423                 test_err("got an error when we shouldn't have");
424                 goto out;
425         }
426         if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
427                 test_err("expected a real extent, got %llu", em->block_start);
428                 goto out;
429         }
430         if (em->start != offset || em->len != 2 * sectorsize) {
431                 test_err(
432         "unexpected extent wanted start %llu len %u, got start %llu len %llu",
433                         offset, 2 * sectorsize, em->start, em->len);
434                 goto out;
435         }
436         if (em->flags != 0) {
437                 test_err("unexpected flags set, want 0 have %u", em->flags);
438                 goto out;
439         }
440         if (em->orig_start != orig_start) {
441                 test_err("wrong orig offset, want %llu, have %llu",
442                          orig_start, em->orig_start);
443                 goto out;
444         }
445         disk_bytenr += (em->start - orig_start);
446         if (em->block_start != disk_bytenr) {
447                 test_err("wrong block start, want %llu, have %llu",
448                          disk_bytenr, em->block_start);
449                 goto out;
450         }
451         offset = em->start + em->len;
452         free_extent_map(em);
453
454         /* Prealloc extent */
455         em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
456         if (IS_ERR(em)) {
457                 test_err("got an error when we shouldn't have");
458                 goto out;
459         }
460         if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
461                 test_err("expected a real extent, got %llu", em->block_start);
462                 goto out;
463         }
464         if (em->start != offset || em->len != sectorsize) {
465                 test_err(
466         "unexpected extent wanted start %llu len %u, got start %llu len %llu",
467                         offset, sectorsize, em->start, em->len);
468                 goto out;
469         }
470         if (em->flags != prealloc_only) {
471                 test_err("unexpected flags set, want %u have %u",
472                          prealloc_only, em->flags);
473                 goto out;
474         }
475         if (em->orig_start != em->start) {
476                 test_err("wrong orig offset, want %llu, have %llu", em->start,
477                          em->orig_start);
478                 goto out;
479         }
480         offset = em->start + em->len;
481         free_extent_map(em);
482
483         /* The next 3 are a half written prealloc extent */
484         em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
485         if (IS_ERR(em)) {
486                 test_err("got an error when we shouldn't have");
487                 goto out;
488         }
489         if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
490                 test_err("expected a real extent, got %llu", em->block_start);
491                 goto out;
492         }
493         if (em->start != offset || em->len != sectorsize) {
494                 test_err(
495         "unexpected extent wanted start %llu len %u, got start %llu len %llu",
496                         offset, sectorsize, em->start, em->len);
497                 goto out;
498         }
499         if (em->flags != prealloc_only) {
500                 test_err("unexpected flags set, want %u have %u",
501                          prealloc_only, em->flags);
502                 goto out;
503         }
504         if (em->orig_start != em->start) {
505                 test_err("wrong orig offset, want %llu, have %llu", em->start,
506                          em->orig_start);
507                 goto out;
508         }
509         disk_bytenr = em->block_start;
510         orig_start = em->start;
511         offset = em->start + em->len;
512         free_extent_map(em);
513
514         em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
515         if (IS_ERR(em)) {
516                 test_err("got an error when we shouldn't have");
517                 goto out;
518         }
519         if (em->block_start >= EXTENT_MAP_HOLE) {
520                 test_err("expected a real extent, got %llu", em->block_start);
521                 goto out;
522         }
523         if (em->start != offset || em->len != sectorsize) {
524                 test_err(
525         "unexpected extent wanted start %llu len %u, got start %llu len %llu",
526                         offset, sectorsize, em->start, em->len);
527                 goto out;
528         }
529         if (em->flags != 0) {
530                 test_err("unexpected flags set, want 0 have %u", em->flags);
531                 goto out;
532         }
533         if (em->orig_start != orig_start) {
534                 test_err("unexpected orig offset, wanted %llu, have %llu",
535                          orig_start, em->orig_start);
536                 goto out;
537         }
538         if (em->block_start != (disk_bytenr + (em->start - em->orig_start))) {
539                 test_err("unexpected block start, wanted %llu, have %llu",
540                          disk_bytenr + (em->start - em->orig_start),
541                          em->block_start);
542                 goto out;
543         }
544         offset = em->start + em->len;
545         free_extent_map(em);
546
547         em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
548         if (IS_ERR(em)) {
549                 test_err("got an error when we shouldn't have");
550                 goto out;
551         }
552         if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
553                 test_err("expected a real extent, got %llu", em->block_start);
554                 goto out;
555         }
556         if (em->start != offset || em->len != 2 * sectorsize) {
557                 test_err(
558         "unexpected extent wanted start %llu len %u, got start %llu len %llu",
559                         offset, 2 * sectorsize, em->start, em->len);
560                 goto out;
561         }
562         if (em->flags != prealloc_only) {
563                 test_err("unexpected flags set, want %u have %u",
564                          prealloc_only, em->flags);
565                 goto out;
566         }
567         if (em->orig_start != orig_start) {
568                 test_err("wrong orig offset, want %llu, have %llu", orig_start,
569                          em->orig_start);
570                 goto out;
571         }
572         if (em->block_start != (disk_bytenr + (em->start - em->orig_start))) {
573                 test_err("unexpected block start, wanted %llu, have %llu",
574                          disk_bytenr + (em->start - em->orig_start),
575                          em->block_start);
576                 goto out;
577         }
578         offset = em->start + em->len;
579         free_extent_map(em);
580
581         /* Now for the compressed extent */
582         em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
583         if (IS_ERR(em)) {
584                 test_err("got an error when we shouldn't have");
585                 goto out;
586         }
587         if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
588                 test_err("expected a real extent, got %llu", em->block_start);
589                 goto out;
590         }
591         if (em->start != offset || em->len != 2 * sectorsize) {
592                 test_err(
593         "unexpected extent wanted start %llu len %u, got start %llu len %llu",
594                         offset, 2 * sectorsize, em->start, em->len);
595                 goto out;
596         }
597         if (em->flags != compressed_only) {
598                 test_err("unexpected flags set, want %u have %u",
599                          compressed_only, em->flags);
600                 goto out;
601         }
602         if (em->orig_start != em->start) {
603                 test_err("wrong orig offset, want %llu, have %llu",
604                          em->start, em->orig_start);
605                 goto out;
606         }
607         if (extent_map_compression(em) != BTRFS_COMPRESS_ZLIB) {
608                 test_err("unexpected compress type, wanted %d, got %d",
609                          BTRFS_COMPRESS_ZLIB, extent_map_compression(em));
610                 goto out;
611         }
612         offset = em->start + em->len;
613         free_extent_map(em);
614
615         /* Split compressed extent */
616         em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
617         if (IS_ERR(em)) {
618                 test_err("got an error when we shouldn't have");
619                 goto out;
620         }
621         if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
622                 test_err("expected a real extent, got %llu", em->block_start);
623                 goto out;
624         }
625         if (em->start != offset || em->len != sectorsize) {
626                 test_err(
627         "unexpected extent wanted start %llu len %u, got start %llu len %llu",
628                         offset, sectorsize, em->start, em->len);
629                 goto out;
630         }
631         if (em->flags != compressed_only) {
632                 test_err("unexpected flags set, want %u have %u",
633                          compressed_only, em->flags);
634                 goto out;
635         }
636         if (em->orig_start != em->start) {
637                 test_err("wrong orig offset, want %llu, have %llu",
638                          em->start, em->orig_start);
639                 goto out;
640         }
641         if (extent_map_compression(em) != BTRFS_COMPRESS_ZLIB) {
642                 test_err("unexpected compress type, wanted %d, got %d",
643                          BTRFS_COMPRESS_ZLIB, extent_map_compression(em));
644                 goto out;
645         }
646         disk_bytenr = em->block_start;
647         orig_start = em->start;
648         offset = em->start + em->len;
649         free_extent_map(em);
650
651         em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
652         if (IS_ERR(em)) {
653                 test_err("got an error when we shouldn't have");
654                 goto out;
655         }
656         if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
657                 test_err("expected a real extent, got %llu", em->block_start);
658                 goto out;
659         }
660         if (em->start != offset || em->len != sectorsize) {
661                 test_err(
662         "unexpected extent wanted start %llu len %u, got start %llu len %llu",
663                         offset, sectorsize, em->start, em->len);
664                 goto out;
665         }
666         if (em->flags != 0) {
667                 test_err("unexpected flags set, want 0 have %u", em->flags);
668                 goto out;
669         }
670         if (em->orig_start != em->start) {
671                 test_err("wrong orig offset, want %llu, have %llu", em->start,
672                          em->orig_start);
673                 goto out;
674         }
675         offset = em->start + em->len;
676         free_extent_map(em);
677
678         em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
679         if (IS_ERR(em)) {
680                 test_err("got an error when we shouldn't have");
681                 goto out;
682         }
683         if (em->block_start != disk_bytenr) {
684                 test_err("block start does not match, want %llu got %llu",
685                          disk_bytenr, em->block_start);
686                 goto out;
687         }
688         if (em->start != offset || em->len != 2 * sectorsize) {
689                 test_err(
690         "unexpected extent wanted start %llu len %u, got start %llu len %llu",
691                         offset, 2 * sectorsize, em->start, em->len);
692                 goto out;
693         }
694         if (em->flags != compressed_only) {
695                 test_err("unexpected flags set, want %u have %u",
696                          compressed_only, em->flags);
697                 goto out;
698         }
699         if (em->orig_start != orig_start) {
700                 test_err("wrong orig offset, want %llu, have %llu",
701                          em->start, orig_start);
702                 goto out;
703         }
704         if (extent_map_compression(em) != BTRFS_COMPRESS_ZLIB) {
705                 test_err("unexpected compress type, wanted %d, got %d",
706                          BTRFS_COMPRESS_ZLIB, extent_map_compression(em));
707                 goto out;
708         }
709         offset = em->start + em->len;
710         free_extent_map(em);
711
712         /* A hole between regular extents but no hole extent */
713         em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset + 6, sectorsize);
714         if (IS_ERR(em)) {
715                 test_err("got an error when we shouldn't have");
716                 goto out;
717         }
718         if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
719                 test_err("expected a real extent, got %llu", em->block_start);
720                 goto out;
721         }
722         if (em->start != offset || em->len != sectorsize) {
723                 test_err(
724         "unexpected extent wanted start %llu len %u, got start %llu len %llu",
725                         offset, sectorsize, em->start, em->len);
726                 goto out;
727         }
728         if (em->flags != 0) {
729                 test_err("unexpected flags set, want 0 have %u", em->flags);
730                 goto out;
731         }
732         if (em->orig_start != em->start) {
733                 test_err("wrong orig offset, want %llu, have %llu", em->start,
734                          em->orig_start);
735                 goto out;
736         }
737         offset = em->start + em->len;
738         free_extent_map(em);
739
740         em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, SZ_4M);
741         if (IS_ERR(em)) {
742                 test_err("got an error when we shouldn't have");
743                 goto out;
744         }
745         if (em->block_start != EXTENT_MAP_HOLE) {
746                 test_err("expected a hole extent, got %llu", em->block_start);
747                 goto out;
748         }
749         /*
750          * Currently we just return a length that we requested rather than the
751          * length of the actual hole, if this changes we'll have to change this
752          * test.
753          */
754         if (em->start != offset || em->len != 3 * sectorsize) {
755                 test_err(
756         "unexpected extent wanted start %llu len %u, got start %llu len %llu",
757                         offset, 3 * sectorsize, em->start, em->len);
758                 goto out;
759         }
760         if (em->flags != vacancy_only) {
761                 test_err("unexpected flags set, want %u have %u",
762                          vacancy_only, em->flags);
763                 goto out;
764         }
765         if (em->orig_start != em->start) {
766                 test_err("wrong orig offset, want %llu, have %llu", em->start,
767                          em->orig_start);
768                 goto out;
769         }
770         offset = em->start + em->len;
771         free_extent_map(em);
772
773         em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, offset, sectorsize);
774         if (IS_ERR(em)) {
775                 test_err("got an error when we shouldn't have");
776                 goto out;
777         }
778         if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
779                 test_err("expected a real extent, got %llu", em->block_start);
780                 goto out;
781         }
782         if (em->start != offset || em->len != sectorsize) {
783                 test_err(
784         "unexpected extent wanted start %llu len %u, got start %llu len %llu",
785                         offset, sectorsize, em->start, em->len);
786                 goto out;
787         }
788         if (em->flags != 0) {
789                 test_err("unexpected flags set, want 0 have %u", em->flags);
790                 goto out;
791         }
792         if (em->orig_start != em->start) {
793                 test_err("wrong orig offset, want %llu, have %llu", em->start,
794                          em->orig_start);
795                 goto out;
796         }
797         ret = 0;
798 out:
799         if (!IS_ERR(em))
800                 free_extent_map(em);
801         iput(inode);
802         btrfs_free_dummy_root(root);
803         btrfs_free_dummy_fs_info(fs_info);
804         return ret;
805 }
806
807 static int test_hole_first(u32 sectorsize, u32 nodesize)
808 {
809         struct btrfs_fs_info *fs_info = NULL;
810         struct inode *inode = NULL;
811         struct btrfs_root *root = NULL;
812         struct extent_map *em = NULL;
813         int ret = -ENOMEM;
814
815         test_msg("running hole first btrfs_get_extent test");
816
817         inode = btrfs_new_test_inode();
818         if (!inode) {
819                 test_std_err(TEST_ALLOC_INODE);
820                 return ret;
821         }
822
823         fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize);
824         if (!fs_info) {
825                 test_std_err(TEST_ALLOC_FS_INFO);
826                 goto out;
827         }
828
829         root = btrfs_alloc_dummy_root(fs_info);
830         if (IS_ERR(root)) {
831                 test_std_err(TEST_ALLOC_ROOT);
832                 goto out;
833         }
834
835         root->node = alloc_dummy_extent_buffer(fs_info, nodesize);
836         if (!root->node) {
837                 test_std_err(TEST_ALLOC_ROOT);
838                 goto out;
839         }
840
841         btrfs_set_header_nritems(root->node, 0);
842         btrfs_set_header_level(root->node, 0);
843         BTRFS_I(inode)->root = root;
844         ret = -EINVAL;
845
846         /*
847          * Need a blank inode item here just so we don't confuse
848          * btrfs_get_extent.
849          */
850         insert_inode_item_key(root);
851         insert_extent(root, sectorsize, sectorsize, sectorsize, 0, sectorsize,
852                       sectorsize, BTRFS_FILE_EXTENT_REG, 0, 1);
853         em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, 0, 2 * sectorsize);
854         if (IS_ERR(em)) {
855                 test_err("got an error when we shouldn't have");
856                 goto out;
857         }
858         if (em->block_start != EXTENT_MAP_HOLE) {
859                 test_err("expected a hole, got %llu", em->block_start);
860                 goto out;
861         }
862         if (em->start != 0 || em->len != sectorsize) {
863                 test_err(
864         "unexpected extent wanted start 0 len %u, got start %llu len %llu",
865                         sectorsize, em->start, em->len);
866                 goto out;
867         }
868         if (em->flags != vacancy_only) {
869                 test_err("wrong flags, wanted %u, have %u", vacancy_only,
870                          em->flags);
871                 goto out;
872         }
873         free_extent_map(em);
874
875         em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, sectorsize, 2 * sectorsize);
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 != sectorsize) {
881                 test_err("expected a real extent, got %llu", em->block_start);
882                 goto out;
883         }
884         if (em->start != sectorsize || em->len != sectorsize) {
885                 test_err(
886         "unexpected extent wanted start %u len %u, got start %llu len %llu",
887                         sectorsize, sectorsize, em->start, em->len);
888                 goto out;
889         }
890         if (em->flags != 0) {
891                 test_err("unexpected flags set, wanted 0 got %u",
892                          em->flags);
893                 goto out;
894         }
895         ret = 0;
896 out:
897         if (!IS_ERR(em))
898                 free_extent_map(em);
899         iput(inode);
900         btrfs_free_dummy_root(root);
901         btrfs_free_dummy_fs_info(fs_info);
902         return ret;
903 }
904
905 static int test_extent_accounting(u32 sectorsize, u32 nodesize)
906 {
907         struct btrfs_fs_info *fs_info = NULL;
908         struct inode *inode = NULL;
909         struct btrfs_root *root = NULL;
910         int ret = -ENOMEM;
911
912         test_msg("running outstanding_extents tests");
913
914         inode = btrfs_new_test_inode();
915         if (!inode) {
916                 test_std_err(TEST_ALLOC_INODE);
917                 return ret;
918         }
919
920         fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize);
921         if (!fs_info) {
922                 test_std_err(TEST_ALLOC_FS_INFO);
923                 goto out;
924         }
925
926         root = btrfs_alloc_dummy_root(fs_info);
927         if (IS_ERR(root)) {
928                 test_std_err(TEST_ALLOC_ROOT);
929                 goto out;
930         }
931
932         BTRFS_I(inode)->root = root;
933
934         /* [BTRFS_MAX_EXTENT_SIZE] */
935         ret = btrfs_set_extent_delalloc(BTRFS_I(inode), 0,
936                                         BTRFS_MAX_EXTENT_SIZE - 1, 0, NULL);
937         if (ret) {
938                 test_err("btrfs_set_extent_delalloc returned %d", ret);
939                 goto out;
940         }
941         if (BTRFS_I(inode)->outstanding_extents != 1) {
942                 ret = -EINVAL;
943                 test_err("miscount, wanted 1, got %u",
944                          BTRFS_I(inode)->outstanding_extents);
945                 goto out;
946         }
947
948         /* [BTRFS_MAX_EXTENT_SIZE][sectorsize] */
949         ret = btrfs_set_extent_delalloc(BTRFS_I(inode), BTRFS_MAX_EXTENT_SIZE,
950                                         BTRFS_MAX_EXTENT_SIZE + sectorsize - 1,
951                                         0, NULL);
952         if (ret) {
953                 test_err("btrfs_set_extent_delalloc returned %d", ret);
954                 goto out;
955         }
956         if (BTRFS_I(inode)->outstanding_extents != 2) {
957                 ret = -EINVAL;
958                 test_err("miscount, wanted 2, got %u",
959                          BTRFS_I(inode)->outstanding_extents);
960                 goto out;
961         }
962
963         /* [BTRFS_MAX_EXTENT_SIZE/2][sectorsize HOLE][the rest] */
964         ret = clear_extent_bit(&BTRFS_I(inode)->io_tree,
965                                BTRFS_MAX_EXTENT_SIZE >> 1,
966                                (BTRFS_MAX_EXTENT_SIZE >> 1) + sectorsize - 1,
967                                EXTENT_DELALLOC | EXTENT_DELALLOC_NEW |
968                                EXTENT_UPTODATE, NULL);
969         if (ret) {
970                 test_err("clear_extent_bit 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][sectorsize] */
981         ret = btrfs_set_extent_delalloc(BTRFS_I(inode), BTRFS_MAX_EXTENT_SIZE >> 1,
982                                         (BTRFS_MAX_EXTENT_SIZE >> 1)
983                                         + sectorsize - 1,
984                                         0, NULL);
985         if (ret) {
986                 test_err("btrfs_set_extent_delalloc returned %d", ret);
987                 goto out;
988         }
989         if (BTRFS_I(inode)->outstanding_extents != 2) {
990                 ret = -EINVAL;
991                 test_err("miscount, wanted 2, got %u",
992                          BTRFS_I(inode)->outstanding_extents);
993                 goto out;
994         }
995
996         /*
997          * [BTRFS_MAX_EXTENT_SIZE+sectorsize][sectorsize HOLE][BTRFS_MAX_EXTENT_SIZE+sectorsize]
998          */
999         ret = btrfs_set_extent_delalloc(BTRFS_I(inode),
1000                         BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize,
1001                         (BTRFS_MAX_EXTENT_SIZE << 1) + 3 * sectorsize - 1,
1002                         0, NULL);
1003         if (ret) {
1004                 test_err("btrfs_set_extent_delalloc returned %d", ret);
1005                 goto out;
1006         }
1007         if (BTRFS_I(inode)->outstanding_extents != 4) {
1008                 ret = -EINVAL;
1009                 test_err("miscount, wanted 4, got %u",
1010                          BTRFS_I(inode)->outstanding_extents);
1011                 goto out;
1012         }
1013
1014         /*
1015         * [BTRFS_MAX_EXTENT_SIZE+sectorsize][sectorsize][BTRFS_MAX_EXTENT_SIZE+sectorsize]
1016         */
1017         ret = btrfs_set_extent_delalloc(BTRFS_I(inode),
1018                         BTRFS_MAX_EXTENT_SIZE + sectorsize,
1019                         BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, 0, NULL);
1020         if (ret) {
1021                 test_err("btrfs_set_extent_delalloc returned %d", ret);
1022                 goto out;
1023         }
1024         if (BTRFS_I(inode)->outstanding_extents != 3) {
1025                 ret = -EINVAL;
1026                 test_err("miscount, wanted 3, got %u",
1027                          BTRFS_I(inode)->outstanding_extents);
1028                 goto out;
1029         }
1030
1031         /* [BTRFS_MAX_EXTENT_SIZE+4k][4K HOLE][BTRFS_MAX_EXTENT_SIZE+4k] */
1032         ret = clear_extent_bit(&BTRFS_I(inode)->io_tree,
1033                                BTRFS_MAX_EXTENT_SIZE + sectorsize,
1034                                BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1,
1035                                EXTENT_DELALLOC | EXTENT_DELALLOC_NEW |
1036                                EXTENT_UPTODATE, NULL);
1037         if (ret) {
1038                 test_err("clear_extent_bit returned %d", ret);
1039                 goto out;
1040         }
1041         if (BTRFS_I(inode)->outstanding_extents != 4) {
1042                 ret = -EINVAL;
1043                 test_err("miscount, wanted 4, got %u",
1044                          BTRFS_I(inode)->outstanding_extents);
1045                 goto out;
1046         }
1047
1048         /*
1049          * Refill the hole again just for good measure, because I thought it
1050          * might fail and I'd rather satisfy my paranoia at this point.
1051          */
1052         ret = btrfs_set_extent_delalloc(BTRFS_I(inode),
1053                         BTRFS_MAX_EXTENT_SIZE + sectorsize,
1054                         BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, 0, NULL);
1055         if (ret) {
1056                 test_err("btrfs_set_extent_delalloc returned %d", ret);
1057                 goto out;
1058         }
1059         if (BTRFS_I(inode)->outstanding_extents != 3) {
1060                 ret = -EINVAL;
1061                 test_err("miscount, wanted 3, got %u",
1062                          BTRFS_I(inode)->outstanding_extents);
1063                 goto out;
1064         }
1065
1066         /* Empty */
1067         ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, (u64)-1,
1068                                EXTENT_DELALLOC | EXTENT_DELALLOC_NEW |
1069                                EXTENT_UPTODATE, NULL);
1070         if (ret) {
1071                 test_err("clear_extent_bit returned %d", ret);
1072                 goto out;
1073         }
1074         if (BTRFS_I(inode)->outstanding_extents) {
1075                 ret = -EINVAL;
1076                 test_err("miscount, wanted 0, got %u",
1077                          BTRFS_I(inode)->outstanding_extents);
1078                 goto out;
1079         }
1080         ret = 0;
1081 out:
1082         if (ret)
1083                 clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, (u64)-1,
1084                                  EXTENT_DELALLOC | EXTENT_DELALLOC_NEW |
1085                                  EXTENT_UPTODATE, NULL);
1086         iput(inode);
1087         btrfs_free_dummy_root(root);
1088         btrfs_free_dummy_fs_info(fs_info);
1089         return ret;
1090 }
1091
1092 int btrfs_test_inodes(u32 sectorsize, u32 nodesize)
1093 {
1094         int ret;
1095
1096         test_msg("running inode tests");
1097
1098         compressed_only |= EXTENT_FLAG_COMPRESS_ZLIB;
1099         prealloc_only |= EXTENT_FLAG_PREALLOC;
1100
1101         ret = test_btrfs_get_extent(sectorsize, nodesize);
1102         if (ret)
1103                 return ret;
1104         ret = test_hole_first(sectorsize, nodesize);
1105         if (ret)
1106                 return ret;
1107         return test_extent_accounting(sectorsize, nodesize);
1108 }