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