brintos

brintos / linux-shallow public Read only

0
0
Text · 30.7 KiB · 3ea3bc2 Raw
1097 lines · c
1// SPDX-License-Identifier: GPL-2.02/*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 16static 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 eb39	 * 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 55static 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 eb73	 * 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 want80 * this so we can test all of the corner cases of btrfs_get_extent.  Here is a81 * diagram of how the extents will look though this may not be possible we still82 * 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 */96static 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 only104	 * exist at file offset 0, thus we can only have one inline file extent105	 * 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 test127	 * 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't152	 * merge our records.153	 */154	disk_bytenr += 2 * sectorsize;155 156	/*157	 * Now for a partially written prealloc extent, basically the same as158	 * the hole punch example above.  Ram_bytes never changes when you mark159	 * 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 214static u32 prealloc_only = 0;215static u32 compressed_only = 0;216static u32 vacancy_only = 0;217 218static 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 in276	 * setup_file_extents, so if you change anything there you need to277	 * 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, as293	 * they are either:294	 *295	 * a) a hidden hole296	 *    The range will be zeroed at inline extent read time.297	 *298	 * b) a file extent with unaligned bytenr299	 *    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 set313	 * unless we have a page for it to write into.  Maybe we should change314	 * 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 the741	 * length of the actual hole, if this changes we'll have to change this742	 * 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;786out: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 795static 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 confuse836	 * 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;884out: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 893static 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 it1038	 * 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;1069out: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 1080int 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