~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/btrfs/tests/inode-tests.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php