xref: /linux/fs/btrfs/tests/inode-tests.c (revision d77b90cfe08f4cf20dbbc255f8ef13bee831be63)
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  * The numbers are using 4K fs block size as an example, the real test will scale
85  * all the extent maps (except the inlined one) according to the block size.
86  *
87  * [ 0  - 6 ][ 6 - 4K       ][ 4K - 8K ][ 8K -  12K      ]
88  * [ inline ][ implied hole ][ regular ][ regular1 split ]
89  *
90  * [ 12K - 16K ][ 16K - 24K      ][ 24K - 28K ][ 28K - 32K ][ 32K - 36K         ]
91  * [ hole      ][ regular1 split ][ prealloc  ][ prealloc1 ][ prealloc1 written ]
92  *
93  * [ 36K - 44K ][ 44K - 52K  ][ 52K - 56K   ][ 56K - 60K ][ 60K - 68 K  ]
94  * [ prealloc1 ][ compressed ][ compressed1 ][ regular   ][ compressed1 ]
95  *
96  * [ 68K - 72K ][ 72K - 84K          ][ 84K - 88K ]
97  * [  regular  ][ hole but no extent ][ regular   ]
98  */
99 static void setup_file_extents(struct btrfs_root *root, u32 sectorsize)
100 {
101 	int slot = 0;
102 	u64 disk_bytenr = SZ_1M;
103 	u64 offset = 0;
104 
105 	/*
106 	 * Start 0, length 6, inlined.
107 	 *
108 	 * Tree-checker has strict limits on inline extents that they can only
109 	 * exist at file offset 0, thus we can only have one inline file extent
110 	 * at most.
111 	 */
112 	insert_extent(root, offset, 6, 6, 0, 0, 0, BTRFS_FILE_EXTENT_INLINE, 0,
113 		      slot);
114 	slot++;
115 	offset = sectorsize;
116 
117 	/* Start 1 * blocksize, length 1 * blocksize, regular. */
118 	insert_extent(root, offset, sectorsize, sectorsize, 0,
119 		      disk_bytenr, sectorsize, BTRFS_FILE_EXTENT_REG, 0, slot);
120 	slot++;
121 
122 	/* We don't want the regular em merged with the next one. */
123 	disk_bytenr += 2 * sectorsize;
124 	offset += sectorsize;
125 
126 	/*
127 	 * Start 2 * blocksize, length 1 * blocksize, regular.
128 	 *
129 	 * Now for 3 extents that were split from a hole punch so we test
130 	 * offsets properly.
131 	 */
132 	insert_extent(root, offset, sectorsize, 4 * sectorsize, 0, disk_bytenr,
133 		      4 * sectorsize, BTRFS_FILE_EXTENT_REG, 0, slot);
134 	slot++;
135 	offset += sectorsize;
136 
137 	/* Start 3 * blocksize, length 1 * blocksize, regular, explicit hole. */
138 	insert_extent(root, offset, sectorsize, sectorsize, 0, 0, 0,
139 		      BTRFS_FILE_EXTENT_REG, 0, slot);
140 	slot++;
141 	offset += sectorsize;
142 
143 	/* Start 4 * blocksize, length 2 * blocksize, regular. */
144 	insert_extent(root, offset, 2 * sectorsize, 4 * sectorsize,
145 		      2 * sectorsize, disk_bytenr, 4 * sectorsize,
146 		      BTRFS_FILE_EXTENT_REG, 0, slot);
147 	slot++;
148 	offset += 2 * sectorsize;
149 	disk_bytenr += 4 * sectorsize;
150 
151 	/* Start 6 * blocksize, length 1 * blocksize, preallocated. */
152 	insert_extent(root, offset, sectorsize, sectorsize, 0, disk_bytenr,
153 		sectorsize, BTRFS_FILE_EXTENT_PREALLOC, 0, slot);
154 	slot++;
155 	offset += sectorsize;
156 
157 	/*
158 	 * We want to jack up disk_bytenr a little more so the em stuff doesn't
159 	 * merge our records.
160 	 */
161 	disk_bytenr += 2 * sectorsize;
162 
163 	/*
164 	 * Start 7 * blocksize, length 1 * blocksize, prealloc.
165 	 *
166 	 * Now for a partially written prealloc extent, basically the same as
167 	 * the hole punch example above.  Ram_bytes never changes when you mark
168 	 * extents written btw.
169 	 */
170 	insert_extent(root, offset, sectorsize, 4 * sectorsize, 0, disk_bytenr,
171 		      4 * sectorsize, BTRFS_FILE_EXTENT_PREALLOC, 0, slot);
172 	slot++;
173 	offset += sectorsize;
174 
175 	/* Start 8 * blocksize, length 1 * blocksize, regular. */
176 	insert_extent(root, offset, sectorsize, 4 * sectorsize, sectorsize,
177 		      disk_bytenr, 4 * sectorsize, BTRFS_FILE_EXTENT_REG, 0,
178 		      slot);
179 	slot++;
180 	offset += sectorsize;
181 
182 	/* Start 9 * blocksize, length 2 * blocksize, prealloc. */
183 	insert_extent(root, offset, 2 * sectorsize, 4 * sectorsize,
184 		      2 * sectorsize, disk_bytenr, 4 * sectorsize,
185 		      BTRFS_FILE_EXTENT_PREALLOC, 0, slot);
186 	slot++;
187 	offset += 2 * sectorsize;
188 	disk_bytenr += 4 * sectorsize;
189 
190 	/* Start 11 * blocksize, length 2 * blocksize, regular. */
191 	insert_extent(root, offset, 2 * sectorsize, 2 * sectorsize, 0,
192 		      disk_bytenr, sectorsize, BTRFS_FILE_EXTENT_REG,
193 		      BTRFS_COMPRESS_ZLIB, slot);
194 	slot++;
195 	offset += 2 * sectorsize;
196 	/* No merges */
197 	disk_bytenr += 2 * sectorsize;
198 
199 	/* Start 13 * blocksize, length 1 * blocksize, regular. */
200 	insert_extent(root, offset, sectorsize, 4 * sectorsize, 0, disk_bytenr,
201 		      sectorsize, BTRFS_FILE_EXTENT_REG,
202 		      BTRFS_COMPRESS_ZLIB, slot);
203 	slot++;
204 	offset += sectorsize;
205 
206 	/* Start 14 * blocksize, length 1 * blocksize, regular. */
207 	insert_extent(root, offset, sectorsize, sectorsize, 0,
208 		      disk_bytenr + sectorsize, sectorsize,
209 		      BTRFS_FILE_EXTENT_REG, 0, slot);
210 	slot++;
211 	offset += sectorsize;
212 
213 	/* Start 15 * blocksize, length 2 * blocksize, regular. */
214 	insert_extent(root, offset, 2 * sectorsize, 4 * sectorsize,
215 		      2 * sectorsize, disk_bytenr, sectorsize,
216 		      BTRFS_FILE_EXTENT_REG, BTRFS_COMPRESS_ZLIB, slot);
217 	slot++;
218 	offset += 2 * sectorsize;
219 	disk_bytenr += 2 * sectorsize;
220 
221 	/* Start 17 * blocksize, length 1 * blocksize, regular. */
222 	insert_extent(root, offset, sectorsize, sectorsize, 0, disk_bytenr,
223 		      sectorsize, BTRFS_FILE_EXTENT_REG, 0, slot);
224 	slot++;
225 	offset += 4 * sectorsize;
226 	disk_bytenr += sectorsize;
227 
228 	/*
229 	 * Start 18 * blocksize, length 3 * blocksize, implied hole (aka no
230 	 * file extent item).
231 	 *
232 	 * Start 21 * blocksize, length 1 * blocksize, regular.
233 	 */
234 	insert_extent(root, offset, sectorsize, sectorsize, 0, disk_bytenr,
235 		      sectorsize, BTRFS_FILE_EXTENT_REG, 0, slot);
236 }
237 
238 static u32 prealloc_only = 0;
239 static u32 compressed_only = 0;
240 static u32 vacancy_only = 0;
241 
242 static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
243 {
244 	struct btrfs_fs_info *fs_info = NULL;
245 	struct inode *inode = NULL;
246 	struct btrfs_root *root = NULL;
247 	struct extent_map *em = NULL;
248 	u64 orig_start;
249 	u64 disk_bytenr;
250 	u64 offset;
251 	int ret = -ENOMEM;
252 
253 	test_msg("running btrfs_get_extent tests");
254 
255 	inode = btrfs_new_test_inode();
256 	if (!inode) {
257 		test_std_err(TEST_ALLOC_INODE);
258 		return ret;
259 	}
260 
261 	fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize);
262 	if (!fs_info) {
263 		test_std_err(TEST_ALLOC_FS_INFO);
264 		goto out;
265 	}
266 
267 	root = btrfs_alloc_dummy_root(fs_info);
268 	if (IS_ERR(root)) {
269 		test_std_err(TEST_ALLOC_ROOT);
270 		goto out;
271 	}
272 
273 	root->node = alloc_dummy_extent_buffer(fs_info, nodesize);
274 	if (!root->node) {
275 		test_std_err(TEST_ALLOC_ROOT);
276 		goto out;
277 	}
278 
279 	btrfs_set_header_nritems(root->node, 0);
280 	btrfs_set_header_level(root->node, 0);
281 	ret = -EINVAL;
282 
283 	/* First with no extents */
284 	BTRFS_I(inode)->root = root;
285 	em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, sectorsize);
286 	if (IS_ERR(em)) {
287 		em = NULL;
288 		test_err("got an error when we shouldn't have");
289 		goto out;
290 	}
291 	if (em->disk_bytenr != EXTENT_MAP_HOLE) {
292 		test_err("expected a hole, got %llu", em->disk_bytenr);
293 		goto out;
294 	}
295 	btrfs_free_extent_map(em);
296 	btrfs_drop_extent_map_range(BTRFS_I(inode), 0, (u64)-1, false);
297 
298 	/*
299 	 * All of the magic numbers are based on the mapping setup in
300 	 * setup_file_extents, so if you change anything there you need to
301 	 * update the comment and update the expected values below.
302 	 */
303 	setup_file_extents(root, sectorsize);
304 
305 	em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, (u64)-1);
306 	if (IS_ERR(em)) {
307 		test_err("got an error when we shouldn't have");
308 		goto out;
309 	}
310 	if (em->disk_bytenr != EXTENT_MAP_INLINE) {
311 		test_err("expected an inline, got %llu", em->disk_bytenr);
312 		goto out;
313 	}
314 
315 	/*
316 	 * For inline extent, we always round up the em to sectorsize, as
317 	 * they are either:
318 	 *
319 	 * a) a hidden hole
320 	 *    The range will be zeroed at inline extent read time.
321 	 *
322 	 * b) a file extent with unaligned bytenr
323 	 *    Tree checker will reject it.
324 	 */
325 	if (em->start != 0 || em->len != sectorsize) {
326 		test_err(
327 	"unexpected extent wanted start 0 len %u, got start %llu len %llu",
328 			sectorsize, em->start, em->len);
329 		goto out;
330 	}
331 	if (em->flags != 0) {
332 		test_err("unexpected flags set, want 0 have %u", em->flags);
333 		goto out;
334 	}
335 	/*
336 	 * We don't test anything else for inline since it doesn't get set
337 	 * unless we have a page for it to write into.  Maybe we should change
338 	 * this?
339 	 */
340 	offset = btrfs_extent_map_end(em);
341 	btrfs_free_extent_map(em);
342 
343 	/* Regular extent */
344 	em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize);
345 	if (IS_ERR(em)) {
346 		test_err("got an error when we shouldn't have");
347 		goto out;
348 	}
349 	if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) {
350 		test_err("expected a real extent, got %llu", em->disk_bytenr);
351 		goto out;
352 	}
353 	if (em->start != offset || em->len != sectorsize) {
354 		test_err(
355 	"unexpected extent wanted start %llu len %u, got start %llu len %llu",
356 			offset, sectorsize, em->start, em->len);
357 		goto out;
358 	}
359 	if (em->flags != 0) {
360 		test_err("unexpected flags set, want 0 have %u", em->flags);
361 		goto out;
362 	}
363 	if (em->offset != 0) {
364 		test_err("wrong offset, want 0, have %llu", em->offset);
365 		goto out;
366 	}
367 	offset = btrfs_extent_map_end(em);
368 	btrfs_free_extent_map(em);
369 
370 	/* The next 3 are split extents */
371 	em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize);
372 	if (IS_ERR(em)) {
373 		test_err("got an error when we shouldn't have");
374 		goto out;
375 	}
376 	if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) {
377 		test_err("expected a real extent, got %llu", em->disk_bytenr);
378 		goto out;
379 	}
380 	if (em->start != offset || em->len != sectorsize) {
381 		test_err(
382 		"unexpected extent start %llu len %u, got start %llu len %llu",
383 			offset, sectorsize, em->start, em->len);
384 		goto out;
385 	}
386 	if (em->flags != 0) {
387 		test_err("unexpected flags set, want 0 have %u", em->flags);
388 		goto out;
389 	}
390 	if (em->offset != 0) {
391 		test_err("wrong offset, want 0, have %llu", em->offset);
392 		goto out;
393 	}
394 	disk_bytenr = btrfs_extent_map_block_start(em);
395 	orig_start = em->start;
396 	offset = btrfs_extent_map_end(em);
397 	btrfs_free_extent_map(em);
398 
399 	em = btrfs_get_extent(BTRFS_I(inode), NULL, 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->disk_bytenr != EXTENT_MAP_HOLE) {
405 		test_err("expected a hole, got %llu", em->disk_bytenr);
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 = btrfs_extent_map_end(em);
419 	btrfs_free_extent_map(em);
420 
421 	em = btrfs_get_extent(BTRFS_I(inode), NULL, 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->disk_bytenr >= EXTENT_MAP_LAST_BYTE) {
427 		test_err("expected a real extent, got %llu", em->disk_bytenr);
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->start - em->offset != orig_start) {
441 		test_err("wrong offset, em->start=%llu em->offset=%llu orig_start=%llu",
442 			 em->start, em->offset, orig_start);
443 		goto out;
444 	}
445 	disk_bytenr += (em->start - orig_start);
446 	if (btrfs_extent_map_block_start(em) != disk_bytenr) {
447 		test_err("wrong block start, want %llu, have %llu",
448 			 disk_bytenr, btrfs_extent_map_block_start(em));
449 		goto out;
450 	}
451 	offset = btrfs_extent_map_end(em);
452 	btrfs_free_extent_map(em);
453 
454 	/* Prealloc extent */
455 	em = btrfs_get_extent(BTRFS_I(inode), NULL, 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->disk_bytenr >= EXTENT_MAP_LAST_BYTE) {
461 		test_err("expected a real extent, got %llu", em->disk_bytenr);
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->offset != 0) {
476 		test_err("wrong offset, want 0, have %llu", em->offset);
477 		goto out;
478 	}
479 	offset = btrfs_extent_map_end(em);
480 	btrfs_free_extent_map(em);
481 
482 	/* The next 3 are a half written prealloc extent */
483 	em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize);
484 	if (IS_ERR(em)) {
485 		test_err("got an error when we shouldn't have");
486 		goto out;
487 	}
488 	if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) {
489 		test_err("expected a real extent, got %llu", em->disk_bytenr);
490 		goto out;
491 	}
492 	if (em->start != offset || em->len != sectorsize) {
493 		test_err(
494 	"unexpected extent wanted start %llu len %u, got start %llu len %llu",
495 			offset, sectorsize, em->start, em->len);
496 		goto out;
497 	}
498 	if (em->flags != prealloc_only) {
499 		test_err("unexpected flags set, want %u have %u",
500 			 prealloc_only, em->flags);
501 		goto out;
502 	}
503 	if (em->offset != 0) {
504 		test_err("wrong offset, want 0, have %llu", em->offset);
505 		goto out;
506 	}
507 	disk_bytenr = btrfs_extent_map_block_start(em);
508 	orig_start = em->start;
509 	offset = btrfs_extent_map_end(em);
510 	btrfs_free_extent_map(em);
511 
512 	em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize);
513 	if (IS_ERR(em)) {
514 		test_err("got an error when we shouldn't have");
515 		goto out;
516 	}
517 	if (em->disk_bytenr >= EXTENT_MAP_HOLE) {
518 		test_err("expected a real extent, got %llu", em->disk_bytenr);
519 		goto out;
520 	}
521 	if (em->start != offset || em->len != sectorsize) {
522 		test_err(
523 	"unexpected extent wanted start %llu len %u, got start %llu len %llu",
524 			offset, sectorsize, em->start, em->len);
525 		goto out;
526 	}
527 	if (em->flags != 0) {
528 		test_err("unexpected flags set, want 0 have %u", em->flags);
529 		goto out;
530 	}
531 	if (em->start - em->offset != orig_start) {
532 		test_err("unexpected offset, wanted %llu, have %llu",
533 			 em->start - orig_start, em->offset);
534 		goto out;
535 	}
536 	if (btrfs_extent_map_block_start(em) != disk_bytenr + em->offset) {
537 		test_err("unexpected block start, wanted %llu, have %llu",
538 			 disk_bytenr + em->offset, btrfs_extent_map_block_start(em));
539 		goto out;
540 	}
541 	offset = btrfs_extent_map_end(em);
542 	btrfs_free_extent_map(em);
543 
544 	em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize);
545 	if (IS_ERR(em)) {
546 		test_err("got an error when we shouldn't have");
547 		goto out;
548 	}
549 	if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) {
550 		test_err("expected a real extent, got %llu", em->disk_bytenr);
551 		goto out;
552 	}
553 	if (em->start != offset || em->len != 2 * sectorsize) {
554 		test_err(
555 	"unexpected extent wanted start %llu len %u, got start %llu len %llu",
556 			offset, 2 * sectorsize, em->start, em->len);
557 		goto out;
558 	}
559 	if (em->flags != prealloc_only) {
560 		test_err("unexpected flags set, want %u have %u",
561 			 prealloc_only, em->flags);
562 		goto out;
563 	}
564 	if (em->start - em->offset != orig_start) {
565 		test_err("wrong offset, em->start=%llu em->offset=%llu orig_start=%llu",
566 			 em->start, em->offset, orig_start);
567 		goto out;
568 	}
569 	if (btrfs_extent_map_block_start(em) != disk_bytenr + em->offset) {
570 		test_err("unexpected block start, wanted %llu, have %llu",
571 			 disk_bytenr + em->offset, btrfs_extent_map_block_start(em));
572 		goto out;
573 	}
574 	offset = btrfs_extent_map_end(em);
575 	btrfs_free_extent_map(em);
576 
577 	/* Now for the compressed extent */
578 	em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize);
579 	if (IS_ERR(em)) {
580 		test_err("got an error when we shouldn't have");
581 		goto out;
582 	}
583 	if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) {
584 		test_err("expected a real extent, got %llu", em->disk_bytenr);
585 		goto out;
586 	}
587 	if (em->start != offset || em->len != 2 * sectorsize) {
588 		test_err(
589 	"unexpected extent wanted start %llu len %u, got start %llu len %llu",
590 			offset, 2 * sectorsize, em->start, em->len);
591 		goto out;
592 	}
593 	if (em->flags != compressed_only) {
594 		test_err("unexpected flags set, want %u have %u",
595 			 compressed_only, em->flags);
596 		goto out;
597 	}
598 	if (em->offset != 0) {
599 		test_err("wrong offset, want 0, have %llu", em->offset);
600 		goto out;
601 	}
602 	if (btrfs_extent_map_compression(em) != BTRFS_COMPRESS_ZLIB) {
603 		test_err("unexpected compress type, wanted %d, got %d",
604 			 BTRFS_COMPRESS_ZLIB, btrfs_extent_map_compression(em));
605 		goto out;
606 	}
607 	offset = btrfs_extent_map_end(em);
608 	btrfs_free_extent_map(em);
609 
610 	/* Split compressed extent */
611 	em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize);
612 	if (IS_ERR(em)) {
613 		test_err("got an error when we shouldn't have");
614 		goto out;
615 	}
616 	if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) {
617 		test_err("expected a real extent, got %llu", em->disk_bytenr);
618 		goto out;
619 	}
620 	if (em->start != offset || em->len != sectorsize) {
621 		test_err(
622 	"unexpected extent wanted start %llu len %u, got start %llu len %llu",
623 			offset, sectorsize, em->start, em->len);
624 		goto out;
625 	}
626 	if (em->flags != compressed_only) {
627 		test_err("unexpected flags set, want %u have %u",
628 			 compressed_only, em->flags);
629 		goto out;
630 	}
631 	if (em->offset != 0) {
632 		test_err("wrong offset, want 0, have %llu", em->offset);
633 		goto out;
634 	}
635 	if (btrfs_extent_map_compression(em) != BTRFS_COMPRESS_ZLIB) {
636 		test_err("unexpected compress type, wanted %d, got %d",
637 			 BTRFS_COMPRESS_ZLIB, btrfs_extent_map_compression(em));
638 		goto out;
639 	}
640 	disk_bytenr = btrfs_extent_map_block_start(em);
641 	orig_start = em->start;
642 	offset = btrfs_extent_map_end(em);
643 	btrfs_free_extent_map(em);
644 
645 	em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize);
646 	if (IS_ERR(em)) {
647 		test_err("got an error when we shouldn't have");
648 		goto out;
649 	}
650 	if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) {
651 		test_err("expected a real extent, got %llu", em->disk_bytenr);
652 		goto out;
653 	}
654 	if (em->start != offset || em->len != sectorsize) {
655 		test_err(
656 	"unexpected extent wanted start %llu len %u, got start %llu len %llu",
657 			offset, sectorsize, em->start, em->len);
658 		goto out;
659 	}
660 	if (em->flags != 0) {
661 		test_err("unexpected flags set, want 0 have %u", em->flags);
662 		goto out;
663 	}
664 	if (em->offset != 0) {
665 		test_err("wrong offset, want 0, have %llu", em->offset);
666 		goto out;
667 	}
668 	offset = btrfs_extent_map_end(em);
669 	btrfs_free_extent_map(em);
670 
671 	em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize);
672 	if (IS_ERR(em)) {
673 		test_err("got an error when we shouldn't have");
674 		goto out;
675 	}
676 	if (btrfs_extent_map_block_start(em) != disk_bytenr) {
677 		test_err("block start does not match, want %llu got %llu",
678 			 disk_bytenr, btrfs_extent_map_block_start(em));
679 		goto out;
680 	}
681 	if (em->start != offset || em->len != 2 * sectorsize) {
682 		test_err(
683 	"unexpected extent wanted start %llu len %u, got start %llu len %llu",
684 			offset, 2 * sectorsize, em->start, em->len);
685 		goto out;
686 	}
687 	if (em->flags != compressed_only) {
688 		test_err("unexpected flags set, want %u have %u",
689 			 compressed_only, em->flags);
690 		goto out;
691 	}
692 	if (em->start - em->offset != orig_start) {
693 		test_err("wrong offset, em->start=%llu em->offset=%llu orig_start=%llu",
694 			 em->start, em->offset, orig_start);
695 		goto out;
696 	}
697 	if (btrfs_extent_map_compression(em) != BTRFS_COMPRESS_ZLIB) {
698 		test_err("unexpected compress type, wanted %d, got %d",
699 			 BTRFS_COMPRESS_ZLIB, btrfs_extent_map_compression(em));
700 		goto out;
701 	}
702 	offset = btrfs_extent_map_end(em);
703 	btrfs_free_extent_map(em);
704 
705 	/* A hole between regular extents but no hole extent */
706 	em = btrfs_get_extent(BTRFS_I(inode), NULL, offset + 6, sectorsize);
707 	if (IS_ERR(em)) {
708 		test_err("got an error when we shouldn't have");
709 		goto out;
710 	}
711 	if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) {
712 		test_err("expected a real extent, got %llu", em->disk_bytenr);
713 		goto out;
714 	}
715 	if (em->start != offset || em->len != sectorsize) {
716 		test_err(
717 	"unexpected extent wanted start %llu len %u, got start %llu len %llu",
718 			offset, sectorsize, em->start, em->len);
719 		goto out;
720 	}
721 	if (em->flags != 0) {
722 		test_err("unexpected flags set, want 0 have %u", em->flags);
723 		goto out;
724 	}
725 	if (em->offset != 0) {
726 		test_err("wrong offset, want 0, have %llu", em->offset);
727 		goto out;
728 	}
729 	offset = btrfs_extent_map_end(em);
730 	btrfs_free_extent_map(em);
731 
732 	em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, SZ_4M);
733 	if (IS_ERR(em)) {
734 		test_err("got an error when we shouldn't have");
735 		goto out;
736 	}
737 	if (em->disk_bytenr != EXTENT_MAP_HOLE) {
738 		test_err("expected a hole extent, got %llu", em->disk_bytenr);
739 		goto out;
740 	}
741 	/*
742 	 * Currently we just return a length that we requested rather than the
743 	 * length of the actual hole, if this changes we'll have to change this
744 	 * test.
745 	 */
746 	if (em->start != offset || em->len != 3 * sectorsize) {
747 		test_err(
748 	"unexpected extent wanted start %llu len %u, got start %llu len %llu",
749 			offset, 3 * sectorsize, em->start, em->len);
750 		goto out;
751 	}
752 	if (em->flags != vacancy_only) {
753 		test_err("unexpected flags set, want %u have %u",
754 			 vacancy_only, em->flags);
755 		goto out;
756 	}
757 	if (em->offset != 0) {
758 		test_err("wrong offset, want 0, have %llu", em->offset);
759 		goto out;
760 	}
761 	offset = btrfs_extent_map_end(em);
762 	btrfs_free_extent_map(em);
763 
764 	em = btrfs_get_extent(BTRFS_I(inode), NULL, offset, sectorsize);
765 	if (IS_ERR(em)) {
766 		test_err("got an error when we shouldn't have");
767 		goto out;
768 	}
769 	if (em->disk_bytenr >= EXTENT_MAP_LAST_BYTE) {
770 		test_err("expected a real extent, got %llu", em->disk_bytenr);
771 		goto out;
772 	}
773 	if (em->start != offset || em->len != sectorsize) {
774 		test_err(
775 	"unexpected extent wanted start %llu len %u, got start %llu len %llu",
776 			offset, sectorsize, em->start, em->len);
777 		goto out;
778 	}
779 	if (em->flags != 0) {
780 		test_err("unexpected flags set, want 0 have %u", em->flags);
781 		goto out;
782 	}
783 	if (em->offset != 0) {
784 		test_err("wrong orig offset, want 0, have %llu", em->offset);
785 		goto out;
786 	}
787 	ret = 0;
788 out:
789 	if (!IS_ERR(em))
790 		btrfs_free_extent_map(em);
791 	iput(inode);
792 	btrfs_free_dummy_root(root);
793 	btrfs_free_dummy_fs_info(fs_info);
794 	return ret;
795 }
796 
797 static int test_hole_first(u32 sectorsize, u32 nodesize)
798 {
799 	struct btrfs_fs_info *fs_info = NULL;
800 	struct inode *inode = NULL;
801 	struct btrfs_root *root = NULL;
802 	struct extent_map *em = NULL;
803 	int ret = -ENOMEM;
804 
805 	test_msg("running hole first btrfs_get_extent test");
806 
807 	inode = btrfs_new_test_inode();
808 	if (!inode) {
809 		test_std_err(TEST_ALLOC_INODE);
810 		return ret;
811 	}
812 
813 	fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize);
814 	if (!fs_info) {
815 		test_std_err(TEST_ALLOC_FS_INFO);
816 		goto out;
817 	}
818 
819 	root = btrfs_alloc_dummy_root(fs_info);
820 	if (IS_ERR(root)) {
821 		test_std_err(TEST_ALLOC_ROOT);
822 		goto out;
823 	}
824 
825 	root->node = alloc_dummy_extent_buffer(fs_info, nodesize);
826 	if (!root->node) {
827 		test_std_err(TEST_ALLOC_ROOT);
828 		goto out;
829 	}
830 
831 	btrfs_set_header_nritems(root->node, 0);
832 	btrfs_set_header_level(root->node, 0);
833 	BTRFS_I(inode)->root = root;
834 	ret = -EINVAL;
835 
836 	/*
837 	 * Need a blank inode item here just so we don't confuse
838 	 * btrfs_get_extent.
839 	 */
840 	insert_inode_item_key(root);
841 	insert_extent(root, sectorsize, sectorsize, sectorsize, 0, sectorsize,
842 		      sectorsize, BTRFS_FILE_EXTENT_REG, 0, 1);
843 	em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, 2 * sectorsize);
844 	if (IS_ERR(em)) {
845 		test_err("got an error when we shouldn't have");
846 		goto out;
847 	}
848 	if (em->disk_bytenr != EXTENT_MAP_HOLE) {
849 		test_err("expected a hole, got %llu", em->disk_bytenr);
850 		goto out;
851 	}
852 	if (em->start != 0 || em->len != sectorsize) {
853 		test_err(
854 	"unexpected extent wanted start 0 len %u, got start %llu len %llu",
855 			sectorsize, em->start, em->len);
856 		goto out;
857 	}
858 	if (em->flags != vacancy_only) {
859 		test_err("wrong flags, wanted %u, have %u", vacancy_only,
860 			 em->flags);
861 		goto out;
862 	}
863 	btrfs_free_extent_map(em);
864 
865 	em = btrfs_get_extent(BTRFS_I(inode), NULL, sectorsize, 2 * sectorsize);
866 	if (IS_ERR(em)) {
867 		test_err("got an error when we shouldn't have");
868 		goto out;
869 	}
870 	if (btrfs_extent_map_block_start(em) != sectorsize) {
871 		test_err("expected a real extent, got %llu",
872 			 btrfs_extent_map_block_start(em));
873 		goto out;
874 	}
875 	if (em->start != sectorsize || em->len != sectorsize) {
876 		test_err(
877 	"unexpected extent wanted start %u len %u, got start %llu len %llu",
878 			sectorsize, sectorsize, em->start, em->len);
879 		goto out;
880 	}
881 	if (em->flags != 0) {
882 		test_err("unexpected flags set, wanted 0 got %u",
883 			 em->flags);
884 		goto out;
885 	}
886 	ret = 0;
887 out:
888 	if (!IS_ERR(em))
889 		btrfs_free_extent_map(em);
890 	iput(inode);
891 	btrfs_free_dummy_root(root);
892 	btrfs_free_dummy_fs_info(fs_info);
893 	return ret;
894 }
895 
896 static int test_extent_accounting(u32 sectorsize, u32 nodesize)
897 {
898 	struct btrfs_fs_info *fs_info = NULL;
899 	struct inode *inode = NULL;
900 	struct btrfs_root *root = NULL;
901 	int ret = -ENOMEM;
902 
903 	test_msg("running outstanding_extents tests");
904 
905 	inode = btrfs_new_test_inode();
906 	if (!inode) {
907 		test_std_err(TEST_ALLOC_INODE);
908 		return ret;
909 	}
910 
911 	fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize);
912 	if (!fs_info) {
913 		test_std_err(TEST_ALLOC_FS_INFO);
914 		goto out;
915 	}
916 
917 	root = btrfs_alloc_dummy_root(fs_info);
918 	if (IS_ERR(root)) {
919 		test_std_err(TEST_ALLOC_ROOT);
920 		goto out;
921 	}
922 
923 	BTRFS_I(inode)->root = root;
924 
925 	/* [BTRFS_MAX_EXTENT_SIZE] */
926 	ret = btrfs_set_extent_delalloc(BTRFS_I(inode), 0,
927 					BTRFS_MAX_EXTENT_SIZE - 1, 0, NULL);
928 	if (ret) {
929 		test_err("btrfs_set_extent_delalloc returned %d", ret);
930 		goto out;
931 	}
932 	if (BTRFS_I(inode)->outstanding_extents != 1) {
933 		ret = -EINVAL;
934 		test_err("miscount, wanted 1, got %u",
935 			 BTRFS_I(inode)->outstanding_extents);
936 		goto out;
937 	}
938 
939 	/* [BTRFS_MAX_EXTENT_SIZE][sectorsize] */
940 	ret = btrfs_set_extent_delalloc(BTRFS_I(inode), BTRFS_MAX_EXTENT_SIZE,
941 					BTRFS_MAX_EXTENT_SIZE + sectorsize - 1,
942 					0, NULL);
943 	if (ret) {
944 		test_err("btrfs_set_extent_delalloc returned %d", ret);
945 		goto out;
946 	}
947 	if (BTRFS_I(inode)->outstanding_extents != 2) {
948 		ret = -EINVAL;
949 		test_err("miscount, wanted 2, got %u",
950 			 BTRFS_I(inode)->outstanding_extents);
951 		goto out;
952 	}
953 
954 	/* [BTRFS_MAX_EXTENT_SIZE/2][sectorsize HOLE][the rest] */
955 	ret = btrfs_clear_extent_bit(&BTRFS_I(inode)->io_tree,
956 				     BTRFS_MAX_EXTENT_SIZE >> 1,
957 				     (BTRFS_MAX_EXTENT_SIZE >> 1) + sectorsize - 1,
958 				     EXTENT_DELALLOC | EXTENT_DELALLOC_NEW, NULL);
959 	if (ret) {
960 		test_err("clear_extent_bit returned %d", ret);
961 		goto out;
962 	}
963 	if (BTRFS_I(inode)->outstanding_extents != 2) {
964 		ret = -EINVAL;
965 		test_err("miscount, wanted 2, got %u",
966 			 BTRFS_I(inode)->outstanding_extents);
967 		goto out;
968 	}
969 
970 	/* [BTRFS_MAX_EXTENT_SIZE][sectorsize] */
971 	ret = btrfs_set_extent_delalloc(BTRFS_I(inode), BTRFS_MAX_EXTENT_SIZE >> 1,
972 					(BTRFS_MAX_EXTENT_SIZE >> 1)
973 					+ sectorsize - 1,
974 					0, NULL);
975 	if (ret) {
976 		test_err("btrfs_set_extent_delalloc returned %d", ret);
977 		goto out;
978 	}
979 	if (BTRFS_I(inode)->outstanding_extents != 2) {
980 		ret = -EINVAL;
981 		test_err("miscount, wanted 2, got %u",
982 			 BTRFS_I(inode)->outstanding_extents);
983 		goto out;
984 	}
985 
986 	/*
987 	 * [BTRFS_MAX_EXTENT_SIZE+sectorsize][sectorsize HOLE][BTRFS_MAX_EXTENT_SIZE+sectorsize]
988 	 */
989 	ret = btrfs_set_extent_delalloc(BTRFS_I(inode),
990 			BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize,
991 			(BTRFS_MAX_EXTENT_SIZE << 1) + 3 * sectorsize - 1,
992 			0, NULL);
993 	if (ret) {
994 		test_err("btrfs_set_extent_delalloc returned %d", ret);
995 		goto out;
996 	}
997 	if (BTRFS_I(inode)->outstanding_extents != 4) {
998 		ret = -EINVAL;
999 		test_err("miscount, wanted 4, got %u",
1000 			 BTRFS_I(inode)->outstanding_extents);
1001 		goto out;
1002 	}
1003 
1004 	/*
1005 	* [BTRFS_MAX_EXTENT_SIZE+sectorsize][sectorsize][BTRFS_MAX_EXTENT_SIZE+sectorsize]
1006 	*/
1007 	ret = btrfs_set_extent_delalloc(BTRFS_I(inode),
1008 			BTRFS_MAX_EXTENT_SIZE + sectorsize,
1009 			BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, 0, NULL);
1010 	if (ret) {
1011 		test_err("btrfs_set_extent_delalloc returned %d", ret);
1012 		goto out;
1013 	}
1014 	if (BTRFS_I(inode)->outstanding_extents != 3) {
1015 		ret = -EINVAL;
1016 		test_err("miscount, wanted 3, got %u",
1017 			 BTRFS_I(inode)->outstanding_extents);
1018 		goto out;
1019 	}
1020 
1021 	/* [BTRFS_MAX_EXTENT_SIZE+4k][4K HOLE][BTRFS_MAX_EXTENT_SIZE+4k] */
1022 	ret = btrfs_clear_extent_bit(&BTRFS_I(inode)->io_tree,
1023 				     BTRFS_MAX_EXTENT_SIZE + sectorsize,
1024 				     BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1,
1025 				     EXTENT_DELALLOC | EXTENT_DELALLOC_NEW, NULL);
1026 	if (ret) {
1027 		test_err("clear_extent_bit returned %d", ret);
1028 		goto out;
1029 	}
1030 	if (BTRFS_I(inode)->outstanding_extents != 4) {
1031 		ret = -EINVAL;
1032 		test_err("miscount, wanted 4, got %u",
1033 			 BTRFS_I(inode)->outstanding_extents);
1034 		goto out;
1035 	}
1036 
1037 	/*
1038 	 * Refill the hole again just for good measure, because I thought it
1039 	 * might fail and I'd rather satisfy my paranoia at this point.
1040 	 */
1041 	ret = btrfs_set_extent_delalloc(BTRFS_I(inode),
1042 			BTRFS_MAX_EXTENT_SIZE + sectorsize,
1043 			BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, 0, NULL);
1044 	if (ret) {
1045 		test_err("btrfs_set_extent_delalloc returned %d", ret);
1046 		goto out;
1047 	}
1048 	if (BTRFS_I(inode)->outstanding_extents != 3) {
1049 		ret = -EINVAL;
1050 		test_err("miscount, wanted 3, got %u",
1051 			 BTRFS_I(inode)->outstanding_extents);
1052 		goto out;
1053 	}
1054 
1055 	/* Empty */
1056 	ret = btrfs_clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, (u64)-1,
1057 				     EXTENT_DELALLOC | EXTENT_DELALLOC_NEW, 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 		btrfs_clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, (u64)-1,
1072 				       EXTENT_DELALLOC | EXTENT_DELALLOC_NEW, NULL);
1073 	iput(inode);
1074 	btrfs_free_dummy_root(root);
1075 	btrfs_free_dummy_fs_info(fs_info);
1076 	return ret;
1077 }
1078 
1079 int btrfs_test_inodes(u32 sectorsize, u32 nodesize)
1080 {
1081 	int ret;
1082 
1083 	test_msg("running inode tests");
1084 
1085 	compressed_only |= EXTENT_FLAG_COMPRESS_ZLIB;
1086 	prealloc_only |= EXTENT_FLAG_PREALLOC;
1087 
1088 	ret = test_btrfs_get_extent(sectorsize, nodesize);
1089 	if (ret)
1090 		return ret;
1091 	ret = test_hole_first(sectorsize, nodesize);
1092 	if (ret)
1093 		return ret;
1094 	return test_extent_accounting(sectorsize, nodesize);
1095 }
1096