diff options
author | Josef Bacik <jbacik@fusionio.com> | 2013-10-11 14:44:09 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2013-11-11 21:57:30 -0500 |
commit | aaedb55bc08f384b7f57dbb3222a511baed4decf (patch) | |
tree | a82118fce66fff847e3412eae4ef7c3c3dc5c616 /fs | |
parent | 294e30fee35d3151d100cfe59e839c2dbc16a374 (diff) |
Btrfs: add tests for btrfs_get_extent
I'm going to be removing hole extents in the near future so I wanted to make a
sanity test for btrfs_get_extent to make sure I don't break anything in the
meantime. This patch just puts btrfs_get_extent through its paces by giving it
a completely unreasonable mapping to look at and make sure it is giving us back
maps that make sense. Thanks,
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/Makefile | 3 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 4 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 8 | ||||
-rw-r--r-- | fs/btrfs/super.c | 3 | ||||
-rw-r--r-- | fs/btrfs/tests/btrfs-tests.c | 8 | ||||
-rw-r--r-- | fs/btrfs/tests/btrfs-tests.h | 5 | ||||
-rw-r--r-- | fs/btrfs/tests/inode-tests.c | 832 |
7 files changed, 861 insertions, 2 deletions
diff --git a/fs/btrfs/Makefile b/fs/btrfs/Makefile index cac4f2d001a3..1a44e42d602a 100644 --- a/fs/btrfs/Makefile +++ b/fs/btrfs/Makefile | |||
@@ -15,4 +15,5 @@ btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o | |||
15 | btrfs-$(CONFIG_BTRFS_FS_CHECK_INTEGRITY) += check-integrity.o | 15 | btrfs-$(CONFIG_BTRFS_FS_CHECK_INTEGRITY) += check-integrity.o |
16 | 16 | ||
17 | btrfs-$(CONFIG_BTRFS_FS_RUN_SANITY_TESTS) += tests/free-space-tests.o \ | 17 | btrfs-$(CONFIG_BTRFS_FS_RUN_SANITY_TESTS) += tests/free-space-tests.o \ |
18 | tests/extent-buffer-tests.o tests/btrfs-tests.o tests/extent-io-tests.o | 18 | tests/extent-buffer-tests.o tests/btrfs-tests.o \ |
19 | tests/extent-io-tests.o tests/inode-tests.o | ||
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 2f398062b942..9f5e1cfb0209 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -4034,5 +4034,9 @@ static inline int btrfs_defrag_cancelled(struct btrfs_fs_info *fs_info) | |||
4034 | return signal_pending(current); | 4034 | return signal_pending(current); |
4035 | } | 4035 | } |
4036 | 4036 | ||
4037 | /* Sanity test specific functions */ | ||
4038 | #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS | ||
4039 | void btrfs_test_destroy_inode(struct inode *inode); | ||
4040 | #endif | ||
4037 | 4041 | ||
4038 | #endif | 4042 | #endif |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index bba7f1a5e9f3..b5c2ad8fe2ca 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -7795,6 +7795,14 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) | |||
7795 | return inode; | 7795 | return inode; |
7796 | } | 7796 | } |
7797 | 7797 | ||
7798 | #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS | ||
7799 | void btrfs_test_destroy_inode(struct inode *inode) | ||
7800 | { | ||
7801 | btrfs_drop_extent_cache(inode, 0, (u64)-1, 0); | ||
7802 | kmem_cache_free(btrfs_inode_cachep, BTRFS_I(inode)); | ||
7803 | } | ||
7804 | #endif | ||
7805 | |||
7798 | static void btrfs_i_callback(struct rcu_head *head) | 7806 | static void btrfs_i_callback(struct rcu_head *head) |
7799 | { | 7807 | { |
7800 | struct inode *inode = container_of(head, struct inode, i_rcu); | 7808 | struct inode *inode = container_of(head, struct inode, i_rcu); |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 78041e34d15a..1f62c1ccab1f 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -1802,6 +1802,9 @@ static int btrfs_run_sanity_tests(void) | |||
1802 | if (ret) | 1802 | if (ret) |
1803 | goto out; | 1803 | goto out; |
1804 | ret = btrfs_test_extent_io(); | 1804 | ret = btrfs_test_extent_io(); |
1805 | if (ret) | ||
1806 | goto out; | ||
1807 | ret = btrfs_test_inodes(); | ||
1805 | out: | 1808 | out: |
1806 | btrfs_destroy_test_fs(); | 1809 | btrfs_destroy_test_fs(); |
1807 | return ret; | 1810 | return ret; |
diff --git a/fs/btrfs/tests/btrfs-tests.c b/fs/btrfs/tests/btrfs-tests.c index 697d527377c1..757ef00a75a4 100644 --- a/fs/btrfs/tests/btrfs-tests.c +++ b/fs/btrfs/tests/btrfs-tests.c | |||
@@ -24,11 +24,17 @@ | |||
24 | 24 | ||
25 | static struct vfsmount *test_mnt = NULL; | 25 | static struct vfsmount *test_mnt = NULL; |
26 | 26 | ||
27 | static const struct super_operations btrfs_test_super_ops = { | ||
28 | .alloc_inode = btrfs_alloc_inode, | ||
29 | .destroy_inode = btrfs_test_destroy_inode, | ||
30 | }; | ||
31 | |||
27 | static struct dentry *btrfs_test_mount(struct file_system_type *fs_type, | 32 | static struct dentry *btrfs_test_mount(struct file_system_type *fs_type, |
28 | int flags, const char *dev_name, | 33 | int flags, const char *dev_name, |
29 | void *data) | 34 | void *data) |
30 | { | 35 | { |
31 | return mount_pseudo(fs_type, "btrfs_test:", NULL, NULL, BTRFS_TEST_MAGIC); | 36 | return mount_pseudo(fs_type, "btrfs_test:", &btrfs_test_super_ops, |
37 | NULL, BTRFS_TEST_MAGIC); | ||
32 | } | 38 | } |
33 | 39 | ||
34 | static struct file_system_type test_type = { | 40 | static struct file_system_type test_type = { |
diff --git a/fs/btrfs/tests/btrfs-tests.h b/fs/btrfs/tests/btrfs-tests.h index e935fe5291e7..b353bc806ca0 100644 --- a/fs/btrfs/tests/btrfs-tests.h +++ b/fs/btrfs/tests/btrfs-tests.h | |||
@@ -26,6 +26,7 @@ | |||
26 | int btrfs_test_free_space_cache(void); | 26 | int btrfs_test_free_space_cache(void); |
27 | int btrfs_test_extent_buffer_operations(void); | 27 | int btrfs_test_extent_buffer_operations(void); |
28 | int btrfs_test_extent_io(void); | 28 | int btrfs_test_extent_io(void); |
29 | int btrfs_test_inodes(void); | ||
29 | int btrfs_init_test_fs(void); | 30 | int btrfs_init_test_fs(void); |
30 | void btrfs_destroy_test_fs(void); | 31 | void btrfs_destroy_test_fs(void); |
31 | struct inode *btrfs_new_test_inode(void); | 32 | struct inode *btrfs_new_test_inode(void); |
@@ -49,6 +50,10 @@ static inline int btrfs_test_extent_io(void) | |||
49 | { | 50 | { |
50 | return 0; | 51 | return 0; |
51 | } | 52 | } |
53 | static inline int btrfs_test_inodes(void) | ||
54 | { | ||
55 | return 0; | ||
56 | } | ||
52 | #endif | 57 | #endif |
53 | 58 | ||
54 | #endif | 59 | #endif |
diff --git a/fs/btrfs/tests/inode-tests.c b/fs/btrfs/tests/inode-tests.c new file mode 100644 index 000000000000..b0fc3bab2a96 --- /dev/null +++ b/fs/btrfs/tests/inode-tests.c | |||
@@ -0,0 +1,832 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 Fusion IO. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public | ||
6 | * License v2 as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
11 | * General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public | ||
14 | * License along with this program; if not, write to the | ||
15 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
16 | * Boston, MA 021110-1307, USA. | ||
17 | */ | ||
18 | |||
19 | #include "btrfs-tests.h" | ||
20 | #include "../ctree.h" | ||
21 | #include "../btrfs_inode.h" | ||
22 | #include "../disk-io.h" | ||
23 | #include "../extent_io.h" | ||
24 | #include "../volumes.h" | ||
25 | |||
26 | static struct btrfs_fs_info *alloc_dummy_fs_info(void) | ||
27 | { | ||
28 | struct btrfs_fs_info *fs_info = kzalloc(sizeof(struct btrfs_fs_info), | ||
29 | GFP_NOFS); | ||
30 | if (!fs_info) | ||
31 | return fs_info; | ||
32 | fs_info->fs_devices = kzalloc(sizeof(struct btrfs_fs_devices), | ||
33 | GFP_NOFS); | ||
34 | if (!fs_info->fs_devices) { | ||
35 | kfree(fs_info); | ||
36 | return NULL; | ||
37 | } | ||
38 | return fs_info; | ||
39 | } | ||
40 | static void free_dummy_root(struct btrfs_root *root) | ||
41 | { | ||
42 | if (!root) | ||
43 | return; | ||
44 | if (root->fs_info) { | ||
45 | kfree(root->fs_info->fs_devices); | ||
46 | kfree(root->fs_info); | ||
47 | } | ||
48 | if (root->node) | ||
49 | free_extent_buffer(root->node); | ||
50 | kfree(root); | ||
51 | } | ||
52 | |||
53 | static void insert_extent(struct btrfs_root *root, u64 start, u64 len, | ||
54 | u64 ram_bytes, u64 offset, u64 disk_bytenr, | ||
55 | u64 disk_len, u32 type, u8 compression, int slot) | ||
56 | { | ||
57 | struct btrfs_path path; | ||
58 | struct btrfs_file_extent_item *fi; | ||
59 | struct extent_buffer *leaf = root->node; | ||
60 | struct btrfs_key key; | ||
61 | u32 value_len = sizeof(struct btrfs_file_extent_item); | ||
62 | |||
63 | if (type == BTRFS_FILE_EXTENT_INLINE) | ||
64 | value_len += len; | ||
65 | memset(&path, 0, sizeof(path)); | ||
66 | |||
67 | path.nodes[0] = leaf; | ||
68 | path.slots[0] = slot; | ||
69 | |||
70 | key.objectid = BTRFS_FIRST_FREE_OBJECTID; | ||
71 | key.type = BTRFS_EXTENT_DATA_KEY; | ||
72 | key.offset = start; | ||
73 | |||
74 | setup_items_for_insert(root, &path, &key, &value_len, value_len, | ||
75 | value_len + sizeof(struct btrfs_item), 1); | ||
76 | fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); | ||
77 | btrfs_set_file_extent_generation(leaf, fi, 1); | ||
78 | btrfs_set_file_extent_type(leaf, fi, type); | ||
79 | btrfs_set_file_extent_disk_bytenr(leaf, fi, disk_bytenr); | ||
80 | btrfs_set_file_extent_disk_num_bytes(leaf, fi, disk_len); | ||
81 | btrfs_set_file_extent_offset(leaf, fi, offset); | ||
82 | btrfs_set_file_extent_num_bytes(leaf, fi, len); | ||
83 | btrfs_set_file_extent_ram_bytes(leaf, fi, ram_bytes); | ||
84 | btrfs_set_file_extent_compression(leaf, fi, compression); | ||
85 | btrfs_set_file_extent_encryption(leaf, fi, 0); | ||
86 | btrfs_set_file_extent_other_encoding(leaf, fi, 0); | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * Build the most complicated map of extents the earth has ever seen. We want | ||
91 | * this so we can test all of the corner cases of btrfs_get_extent. Here is a | ||
92 | * diagram of how the extents will look though this may not be possible we still | ||
93 | * want to make sure everything acts normally (the last number is not inclusive) | ||
94 | * | ||
95 | * [0 - 5][5 - 6][6 - 10][10 - 4096][ 4096 - 8192 ][8192 - 12288] | ||
96 | * [hole ][inline][ hole ][ regular ][regular1 split][ hole ] | ||
97 | * | ||
98 | * [ 12288 - 20480][20480 - 24576][ 24576 - 28672 ][28672 - 36864][36864 - 45056] | ||
99 | * [regular1 split][ prealloc1 ][prealloc1 written][ prealloc1 ][ compressed ] | ||
100 | * | ||
101 | * [45056 - 49152][49152-53248][53248-61440][61440-65536][ 65536+81920 ] | ||
102 | * [ compressed1 ][ regular ][compressed1][ regular ][ hole but no extent] | ||
103 | * | ||
104 | * [81920-86016] | ||
105 | * [ regular ] | ||
106 | */ | ||
107 | static void setup_file_extents(struct btrfs_root *root) | ||
108 | { | ||
109 | int slot = 0; | ||
110 | u64 disk_bytenr = 1 * 1024 * 1024; | ||
111 | u64 offset = 0; | ||
112 | |||
113 | /* First we want a hole */ | ||
114 | insert_extent(root, offset, 5, 5, 0, 0, 0, BTRFS_FILE_EXTENT_REG, 0, | ||
115 | slot); | ||
116 | slot++; | ||
117 | offset += 5; | ||
118 | |||
119 | /* | ||
120 | * Now we want an inline extent, I don't think this is possible but hey | ||
121 | * why not? Also keep in mind if we have an inline extent it counts as | ||
122 | * the whole first page. If we were to expand it we would have to cow | ||
123 | * and we wouldn't have an inline extent anymore. | ||
124 | */ | ||
125 | insert_extent(root, offset, 1, 1, 0, 0, 0, BTRFS_FILE_EXTENT_INLINE, 0, | ||
126 | slot); | ||
127 | slot++; | ||
128 | offset = 4096; | ||
129 | |||
130 | /* Now another hole */ | ||
131 | insert_extent(root, offset, 4, 4, 0, 0, 0, BTRFS_FILE_EXTENT_REG, 0, | ||
132 | slot); | ||
133 | slot++; | ||
134 | offset += 4; | ||
135 | |||
136 | /* Now for a regular extent */ | ||
137 | insert_extent(root, offset, 4095, 4095, 0, disk_bytenr, 4096, | ||
138 | BTRFS_FILE_EXTENT_REG, 0, slot); | ||
139 | slot++; | ||
140 | disk_bytenr += 4096; | ||
141 | offset += 4095; | ||
142 | |||
143 | /* | ||
144 | * Now for 3 extents that were split from a hole punch so we test | ||
145 | * offsets properly. | ||
146 | */ | ||
147 | insert_extent(root, offset, 4096, 16384, 0, disk_bytenr, 16384, | ||
148 | BTRFS_FILE_EXTENT_REG, 0, slot); | ||
149 | slot++; | ||
150 | offset += 4096; | ||
151 | insert_extent(root, offset, 4096, 4096, 0, 0, 0, BTRFS_FILE_EXTENT_REG, | ||
152 | 0, slot); | ||
153 | slot++; | ||
154 | offset += 4096; | ||
155 | insert_extent(root, offset, 8192, 16384, 8192, disk_bytenr, 16384, | ||
156 | BTRFS_FILE_EXTENT_REG, 0, slot); | ||
157 | slot++; | ||
158 | offset += 8192; | ||
159 | disk_bytenr += 16384; | ||
160 | |||
161 | /* Now for a unwritten prealloc extent */ | ||
162 | insert_extent(root, offset, 4096, 4096, 0, disk_bytenr, 4096, | ||
163 | BTRFS_FILE_EXTENT_PREALLOC, 0, slot); | ||
164 | slot++; | ||
165 | offset += 4096; | ||
166 | |||
167 | /* | ||
168 | * We want to jack up disk_bytenr a little more so the em stuff doesn't | ||
169 | * merge our records. | ||
170 | */ | ||
171 | disk_bytenr += 8192; | ||
172 | |||
173 | /* | ||
174 | * Now for a partially written prealloc extent, basically the same as | ||
175 | * the hole punch example above. Ram_bytes never changes when you mark | ||
176 | * extents written btw. | ||
177 | */ | ||
178 | insert_extent(root, offset, 4096, 16384, 0, disk_bytenr, 16384, | ||
179 | BTRFS_FILE_EXTENT_PREALLOC, 0, slot); | ||
180 | slot++; | ||
181 | offset += 4096; | ||
182 | insert_extent(root, offset, 4096, 16384, 4096, disk_bytenr, 16384, | ||
183 | BTRFS_FILE_EXTENT_REG, 0, slot); | ||
184 | slot++; | ||
185 | offset += 4096; | ||
186 | insert_extent(root, offset, 8192, 16384, 8192, disk_bytenr, 16384, | ||
187 | BTRFS_FILE_EXTENT_PREALLOC, 0, slot); | ||
188 | slot++; | ||
189 | offset += 8192; | ||
190 | disk_bytenr += 16384; | ||
191 | |||
192 | /* Now a normal compressed extent */ | ||
193 | insert_extent(root, offset, 8192, 8192, 0, disk_bytenr, 4096, | ||
194 | BTRFS_FILE_EXTENT_REG, BTRFS_COMPRESS_ZLIB, slot); | ||
195 | slot++; | ||
196 | offset += 8192; | ||
197 | /* No merges */ | ||
198 | disk_bytenr += 8192; | ||
199 | |||
200 | /* Now a split compressed extent */ | ||
201 | insert_extent(root, offset, 4096, 16384, 0, disk_bytenr, 4096, | ||
202 | BTRFS_FILE_EXTENT_REG, BTRFS_COMPRESS_ZLIB, slot); | ||
203 | slot++; | ||
204 | offset += 4096; | ||
205 | insert_extent(root, offset, 4096, 4096, 0, disk_bytenr + 4096, 4096, | ||
206 | BTRFS_FILE_EXTENT_REG, 0, slot); | ||
207 | slot++; | ||
208 | offset += 4096; | ||
209 | insert_extent(root, offset, 8192, 16384, 8192, disk_bytenr, 4096, | ||
210 | BTRFS_FILE_EXTENT_REG, BTRFS_COMPRESS_ZLIB, slot); | ||
211 | slot++; | ||
212 | offset += 8192; | ||
213 | disk_bytenr += 8192; | ||
214 | |||
215 | /* Now extents that have a hole but no hole extent */ | ||
216 | insert_extent(root, offset, 4096, 4096, 0, disk_bytenr, 4096, | ||
217 | BTRFS_FILE_EXTENT_REG, 0, slot); | ||
218 | slot++; | ||
219 | offset += 16384; | ||
220 | disk_bytenr += 4096; | ||
221 | insert_extent(root, offset, 4096, 4096, 0, disk_bytenr, 4096, | ||
222 | BTRFS_FILE_EXTENT_REG, 0, slot); | ||
223 | } | ||
224 | |||
225 | static unsigned long prealloc_only = 0; | ||
226 | static unsigned long compressed_only = 0; | ||
227 | static unsigned long vacancy_only = 0; | ||
228 | |||
229 | static noinline int test_btrfs_get_extent(void) | ||
230 | { | ||
231 | struct inode *inode = NULL; | ||
232 | struct btrfs_root *root = NULL; | ||
233 | struct extent_map *em = NULL; | ||
234 | u64 orig_start; | ||
235 | u64 disk_bytenr; | ||
236 | u64 offset; | ||
237 | int ret = -ENOMEM; | ||
238 | |||
239 | set_bit(EXTENT_FLAG_COMPRESSED, &compressed_only); | ||
240 | set_bit(EXTENT_FLAG_VACANCY, &vacancy_only); | ||
241 | set_bit(EXTENT_FLAG_PREALLOC, &prealloc_only); | ||
242 | |||
243 | inode = btrfs_new_test_inode(); | ||
244 | if (!inode) { | ||
245 | test_msg("Couldn't allocate inode\n"); | ||
246 | return ret; | ||
247 | } | ||
248 | |||
249 | BTRFS_I(inode)->location.type = BTRFS_INODE_ITEM_KEY; | ||
250 | BTRFS_I(inode)->location.objectid = BTRFS_FIRST_FREE_OBJECTID; | ||
251 | BTRFS_I(inode)->location.offset = 0; | ||
252 | |||
253 | root = btrfs_alloc_dummy_root(); | ||
254 | if (IS_ERR(root)) { | ||
255 | test_msg("Couldn't allocate root\n"); | ||
256 | goto out; | ||
257 | } | ||
258 | |||
259 | /* | ||
260 | * We do this since btrfs_get_extent wants to assign em->bdev to | ||
261 | * root->fs_info->fs_devices->latest_bdev. | ||
262 | */ | ||
263 | root->fs_info = alloc_dummy_fs_info(); | ||
264 | if (!root->fs_info) { | ||
265 | test_msg("Couldn't allocate dummy fs info\n"); | ||
266 | goto out; | ||
267 | } | ||
268 | |||
269 | root->node = alloc_dummy_extent_buffer(0, 4096); | ||
270 | if (!root->node) { | ||
271 | test_msg("Couldn't allocate dummy buffer\n"); | ||
272 | goto out; | ||
273 | } | ||
274 | |||
275 | /* | ||
276 | * We will just free a dummy node if it's ref count is 2 so we need an | ||
277 | * extra ref so our searches don't accidently release our page. | ||
278 | */ | ||
279 | extent_buffer_get(root->node); | ||
280 | btrfs_set_header_nritems(root->node, 0); | ||
281 | btrfs_set_header_level(root->node, 0); | ||
282 | ret = -EINVAL; | ||
283 | |||
284 | /* First with no extents */ | ||
285 | BTRFS_I(inode)->root = root; | ||
286 | em = btrfs_get_extent(inode, NULL, 0, 0, 4096, 0); | ||
287 | if (IS_ERR(em)) { | ||
288 | em = NULL; | ||
289 | test_msg("Got an error when we shouldn't have\n"); | ||
290 | goto out; | ||
291 | } | ||
292 | if (em->block_start != EXTENT_MAP_HOLE) { | ||
293 | test_msg("Expected a hole, got %llu\n", em->block_start); | ||
294 | goto out; | ||
295 | } | ||
296 | if (!test_bit(EXTENT_FLAG_VACANCY, &em->flags)) { | ||
297 | test_msg("Vacancy flag wasn't set properly\n"); | ||
298 | goto out; | ||
299 | } | ||
300 | free_extent_map(em); | ||
301 | btrfs_drop_extent_cache(inode, 0, (u64)-1, 0); | ||
302 | |||
303 | /* | ||
304 | * All of the magic numbers are based on the mapping setup in | ||
305 | * setup_file_extents, so if you change anything there you need to | ||
306 | * update the comment and update the expected values below. | ||
307 | */ | ||
308 | setup_file_extents(root); | ||
309 | |||
310 | em = btrfs_get_extent(inode, NULL, 0, 0, (u64)-1, 0); | ||
311 | if (IS_ERR(em)) { | ||
312 | test_msg("Got an error when we shouldn't have\n"); | ||
313 | goto out; | ||
314 | } | ||
315 | if (em->block_start != EXTENT_MAP_HOLE) { | ||
316 | test_msg("Expected a hole, got %llu\n", em->block_start); | ||
317 | goto out; | ||
318 | } | ||
319 | if (em->start != 0 || em->len != 5) { | ||
320 | test_msg("Unexpected extent wanted start 0 len 5, got start " | ||
321 | "%llu len %llu\n", em->start, em->len); | ||
322 | goto out; | ||
323 | } | ||
324 | if (em->flags != 0) { | ||
325 | test_msg("Unexpected flags set, want 0 have %lu\n", em->flags); | ||
326 | goto out; | ||
327 | } | ||
328 | offset = em->start + em->len; | ||
329 | free_extent_map(em); | ||
330 | |||
331 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | ||
332 | if (IS_ERR(em)) { | ||
333 | test_msg("Got an error when we shouldn't have\n"); | ||
334 | goto out; | ||
335 | } | ||
336 | if (em->block_start != EXTENT_MAP_INLINE) { | ||
337 | test_msg("Expected an inline, got %llu\n", em->block_start); | ||
338 | goto out; | ||
339 | } | ||
340 | if (em->start != offset || em->len != 4091) { | ||
341 | test_msg("Unexpected extent wanted start %llu len 1, got start " | ||
342 | "%llu len %llu\n", offset, em->start, em->len); | ||
343 | goto out; | ||
344 | } | ||
345 | if (em->flags != 0) { | ||
346 | test_msg("Unexpected flags set, want 0 have %lu\n", em->flags); | ||
347 | goto out; | ||
348 | } | ||
349 | /* | ||
350 | * We don't test anything else for inline since it doesn't get set | ||
351 | * unless we have a page for it to write into. Maybe we should change | ||
352 | * this? | ||
353 | */ | ||
354 | offset = em->start + em->len; | ||
355 | free_extent_map(em); | ||
356 | |||
357 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | ||
358 | if (IS_ERR(em)) { | ||
359 | test_msg("Got an error when we shouldn't have\n"); | ||
360 | goto out; | ||
361 | } | ||
362 | if (em->block_start != EXTENT_MAP_HOLE) { | ||
363 | test_msg("Expected a hole, got %llu\n", em->block_start); | ||
364 | goto out; | ||
365 | } | ||
366 | if (em->start != offset || em->len != 4) { | ||
367 | test_msg("Unexpected extent wanted start %llu len 4, got start " | ||
368 | "%llu len %llu\n", offset, em->start, em->len); | ||
369 | goto out; | ||
370 | } | ||
371 | if (em->flags != 0) { | ||
372 | test_msg("Unexpected flags set, want 0 have %lu\n", em->flags); | ||
373 | goto out; | ||
374 | } | ||
375 | offset = em->start + em->len; | ||
376 | free_extent_map(em); | ||
377 | |||
378 | /* Regular extent */ | ||
379 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | ||
380 | if (IS_ERR(em)) { | ||
381 | test_msg("Got an error when we shouldn't have\n"); | ||
382 | goto out; | ||
383 | } | ||
384 | if (em->block_start >= EXTENT_MAP_LAST_BYTE) { | ||
385 | test_msg("Expected a real extent, got %llu\n", em->block_start); | ||
386 | goto out; | ||
387 | } | ||
388 | if (em->start != offset || em->len != 4095) { | ||
389 | test_msg("Unexpected extent wanted start %llu len 4095, got " | ||
390 | "start %llu len %llu\n", offset, em->start, em->len); | ||
391 | goto out; | ||
392 | } | ||
393 | if (em->flags != 0) { | ||
394 | test_msg("Unexpected flags set, want 0 have %lu\n", em->flags); | ||
395 | goto out; | ||
396 | } | ||
397 | if (em->orig_start != em->start) { | ||
398 | test_msg("Wrong orig offset, want %llu, have %llu\n", em->start, | ||
399 | em->orig_start); | ||
400 | goto out; | ||
401 | } | ||
402 | offset = em->start + em->len; | ||
403 | free_extent_map(em); | ||
404 | |||
405 | /* The next 3 are split extents */ | ||
406 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | ||
407 | if (IS_ERR(em)) { | ||
408 | test_msg("Got an error when we shouldn't have\n"); | ||
409 | goto out; | ||
410 | } | ||
411 | if (em->block_start >= EXTENT_MAP_LAST_BYTE) { | ||
412 | test_msg("Expected a real extent, got %llu\n", em->block_start); | ||
413 | goto out; | ||
414 | } | ||
415 | if (em->start != offset || em->len != 4096) { | ||
416 | test_msg("Unexpected extent wanted start %llu len 4096, got " | ||
417 | "start %llu len %llu\n", offset, em->start, em->len); | ||
418 | goto out; | ||
419 | } | ||
420 | if (em->flags != 0) { | ||
421 | test_msg("Unexpected flags set, want 0 have %lu\n", em->flags); | ||
422 | goto out; | ||
423 | } | ||
424 | if (em->orig_start != em->start) { | ||
425 | test_msg("Wrong orig offset, want %llu, have %llu\n", em->start, | ||
426 | em->orig_start); | ||
427 | goto out; | ||
428 | } | ||
429 | disk_bytenr = em->block_start; | ||
430 | orig_start = em->start; | ||
431 | offset = em->start + em->len; | ||
432 | free_extent_map(em); | ||
433 | |||
434 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | ||
435 | if (IS_ERR(em)) { | ||
436 | test_msg("Got an error when we shouldn't have\n"); | ||
437 | goto out; | ||
438 | } | ||
439 | if (em->block_start != EXTENT_MAP_HOLE) { | ||
440 | test_msg("Expected a hole, got %llu\n", em->block_start); | ||
441 | goto out; | ||
442 | } | ||
443 | if (em->start != offset || em->len != 4096) { | ||
444 | test_msg("Unexpected extent wanted start %llu len 4096, got " | ||
445 | "start %llu len %llu\n", offset, em->start, em->len); | ||
446 | goto out; | ||
447 | } | ||
448 | if (em->flags != 0) { | ||
449 | test_msg("Unexpected flags set, want 0 have %lu\n", em->flags); | ||
450 | goto out; | ||
451 | } | ||
452 | offset = em->start + em->len; | ||
453 | free_extent_map(em); | ||
454 | |||
455 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | ||
456 | if (IS_ERR(em)) { | ||
457 | test_msg("Got an error when we shouldn't have\n"); | ||
458 | goto out; | ||
459 | } | ||
460 | if (em->block_start >= EXTENT_MAP_LAST_BYTE) { | ||
461 | test_msg("Expected a real extent, got %llu\n", em->block_start); | ||
462 | goto out; | ||
463 | } | ||
464 | if (em->start != offset || em->len != 8192) { | ||
465 | test_msg("Unexpected extent wanted start %llu len 8192, got " | ||
466 | "start %llu len %llu\n", offset, em->start, em->len); | ||
467 | goto out; | ||
468 | } | ||
469 | if (em->flags != 0) { | ||
470 | test_msg("Unexpected flags set, want 0 have %lu\n", em->flags); | ||
471 | goto out; | ||
472 | } | ||
473 | if (em->orig_start != orig_start) { | ||
474 | test_msg("Wrong orig offset, want %llu, have %llu\n", | ||
475 | orig_start, em->orig_start); | ||
476 | goto out; | ||
477 | } | ||
478 | disk_bytenr += (em->start - orig_start); | ||
479 | if (em->block_start != disk_bytenr) { | ||
480 | test_msg("Wrong block start, want %llu, have %llu\n", | ||
481 | disk_bytenr, em->block_start); | ||
482 | goto out; | ||
483 | } | ||
484 | offset = em->start + em->len; | ||
485 | free_extent_map(em); | ||
486 | |||
487 | /* Prealloc extent */ | ||
488 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | ||
489 | if (IS_ERR(em)) { | ||
490 | test_msg("Got an error when we shouldn't have\n"); | ||
491 | goto out; | ||
492 | } | ||
493 | if (em->block_start >= EXTENT_MAP_LAST_BYTE) { | ||
494 | test_msg("Expected a real extent, got %llu\n", em->block_start); | ||
495 | goto out; | ||
496 | } | ||
497 | if (em->start != offset || em->len != 4096) { | ||
498 | test_msg("Unexpected extent wanted start %llu len 4096, got " | ||
499 | "start %llu len %llu\n", offset, em->start, em->len); | ||
500 | goto out; | ||
501 | } | ||
502 | if (em->flags != prealloc_only) { | ||
503 | test_msg("Unexpected flags set, want %lu have %lu\n", | ||
504 | prealloc_only, em->flags); | ||
505 | goto out; | ||
506 | } | ||
507 | if (em->orig_start != em->start) { | ||
508 | test_msg("Wrong orig offset, want %llu, have %llu\n", em->start, | ||
509 | em->orig_start); | ||
510 | goto out; | ||
511 | } | ||
512 | offset = em->start + em->len; | ||
513 | free_extent_map(em); | ||
514 | |||
515 | /* The next 3 are a half written prealloc extent */ | ||
516 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | ||
517 | if (IS_ERR(em)) { | ||
518 | test_msg("Got an error when we shouldn't have\n"); | ||
519 | goto out; | ||
520 | } | ||
521 | if (em->block_start >= EXTENT_MAP_LAST_BYTE) { | ||
522 | test_msg("Expected a real extent, got %llu\n", em->block_start); | ||
523 | goto out; | ||
524 | } | ||
525 | if (em->start != offset || em->len != 4096) { | ||
526 | test_msg("Unexpected extent wanted start %llu len 4096, got " | ||
527 | "start %llu len %llu\n", offset, em->start, em->len); | ||
528 | goto out; | ||
529 | } | ||
530 | if (em->flags != prealloc_only) { | ||
531 | test_msg("Unexpected flags set, want %lu have %lu\n", | ||
532 | prealloc_only, em->flags); | ||
533 | goto out; | ||
534 | } | ||
535 | if (em->orig_start != em->start) { | ||
536 | test_msg("Wrong orig offset, want %llu, have %llu\n", em->start, | ||
537 | em->orig_start); | ||
538 | goto out; | ||
539 | } | ||
540 | disk_bytenr = em->block_start; | ||
541 | orig_start = em->start; | ||
542 | offset = em->start + em->len; | ||
543 | free_extent_map(em); | ||
544 | |||
545 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | ||
546 | if (IS_ERR(em)) { | ||
547 | test_msg("Got an error when we shouldn't have\n"); | ||
548 | goto out; | ||
549 | } | ||
550 | if (em->block_start >= EXTENT_MAP_HOLE) { | ||
551 | test_msg("Expected a real extent, got %llu\n", em->block_start); | ||
552 | goto out; | ||
553 | } | ||
554 | if (em->start != offset || em->len != 4096) { | ||
555 | test_msg("Unexpected extent wanted start %llu len 4096, got " | ||
556 | "start %llu len %llu\n", offset, em->start, em->len); | ||
557 | goto out; | ||
558 | } | ||
559 | if (em->flags != 0) { | ||
560 | test_msg("Unexpected flags set, want 0 have %lu\n", em->flags); | ||
561 | goto out; | ||
562 | } | ||
563 | if (em->orig_start != orig_start) { | ||
564 | test_msg("Unexpected orig offset, wanted %llu, have %llu\n", | ||
565 | orig_start, em->orig_start); | ||
566 | goto out; | ||
567 | } | ||
568 | if (em->block_start != (disk_bytenr + (em->start - em->orig_start))) { | ||
569 | test_msg("Unexpected block start, wanted %llu, have %llu\n", | ||
570 | disk_bytenr + (em->start - em->orig_start), | ||
571 | em->block_start); | ||
572 | goto out; | ||
573 | } | ||
574 | offset = em->start + em->len; | ||
575 | free_extent_map(em); | ||
576 | |||
577 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | ||
578 | if (IS_ERR(em)) { | ||
579 | test_msg("Got an error when we shouldn't have\n"); | ||
580 | goto out; | ||
581 | } | ||
582 | if (em->block_start >= EXTENT_MAP_LAST_BYTE) { | ||
583 | test_msg("Expected a real extent, got %llu\n", em->block_start); | ||
584 | goto out; | ||
585 | } | ||
586 | if (em->start != offset || em->len != 8192) { | ||
587 | test_msg("Unexpected extent wanted start %llu len 8192, got " | ||
588 | "start %llu len %llu\n", offset, em->start, em->len); | ||
589 | goto out; | ||
590 | } | ||
591 | if (em->flags != prealloc_only) { | ||
592 | test_msg("Unexpected flags set, want %lu have %lu\n", | ||
593 | prealloc_only, em->flags); | ||
594 | goto out; | ||
595 | } | ||
596 | if (em->orig_start != orig_start) { | ||
597 | test_msg("Wrong orig offset, want %llu, have %llu\n", orig_start, | ||
598 | em->orig_start); | ||
599 | goto out; | ||
600 | } | ||
601 | if (em->block_start != (disk_bytenr + (em->start - em->orig_start))) { | ||
602 | test_msg("Unexpected block start, wanted %llu, have %llu\n", | ||
603 | disk_bytenr + (em->start - em->orig_start), | ||
604 | em->block_start); | ||
605 | goto out; | ||
606 | } | ||
607 | offset = em->start + em->len; | ||
608 | free_extent_map(em); | ||
609 | |||
610 | /* Now for the compressed extent */ | ||
611 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | ||
612 | if (IS_ERR(em)) { | ||
613 | test_msg("Got an error when we shouldn't have\n"); | ||
614 | goto out; | ||
615 | } | ||
616 | if (em->block_start >= EXTENT_MAP_LAST_BYTE) { | ||
617 | test_msg("Expected a real extent, got %llu\n", em->block_start); | ||
618 | goto out; | ||
619 | } | ||
620 | if (em->start != offset || em->len != 8192) { | ||
621 | test_msg("Unexpected extent wanted start %llu len 8192, got " | ||
622 | "start %llu len %llu\n", offset, em->start, em->len); | ||
623 | goto out; | ||
624 | } | ||
625 | if (em->flags != compressed_only) { | ||
626 | test_msg("Unexpected flags set, want %lu have %lu\n", | ||
627 | compressed_only, em->flags); | ||
628 | goto out; | ||
629 | } | ||
630 | if (em->orig_start != em->start) { | ||
631 | test_msg("Wrong orig offset, want %llu, have %llu\n", | ||
632 | em->start, em->orig_start); | ||
633 | goto out; | ||
634 | } | ||
635 | if (em->compress_type != BTRFS_COMPRESS_ZLIB) { | ||
636 | test_msg("Unexpected compress type, wanted %d, got %d\n", | ||
637 | BTRFS_COMPRESS_ZLIB, em->compress_type); | ||
638 | goto out; | ||
639 | } | ||
640 | offset = em->start + em->len; | ||
641 | free_extent_map(em); | ||
642 | |||
643 | /* Split compressed extent */ | ||
644 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | ||
645 | if (IS_ERR(em)) { | ||
646 | test_msg("Got an error when we shouldn't have\n"); | ||
647 | goto out; | ||
648 | } | ||
649 | if (em->block_start >= EXTENT_MAP_LAST_BYTE) { | ||
650 | test_msg("Expected a real extent, got %llu\n", em->block_start); | ||
651 | goto out; | ||
652 | } | ||
653 | if (em->start != offset || em->len != 4096) { | ||
654 | test_msg("Unexpected extent wanted start %llu len 4096, got " | ||
655 | "start %llu len %llu\n", offset, em->start, em->len); | ||
656 | goto out; | ||
657 | } | ||
658 | if (em->flags != compressed_only) { | ||
659 | test_msg("Unexpected flags set, want %lu have %lu\n", | ||
660 | compressed_only, em->flags); | ||
661 | goto out; | ||
662 | } | ||
663 | if (em->orig_start != em->start) { | ||
664 | test_msg("Wrong orig offset, want %llu, have %llu\n", | ||
665 | em->start, em->orig_start); | ||
666 | goto out; | ||
667 | } | ||
668 | if (em->compress_type != BTRFS_COMPRESS_ZLIB) { | ||
669 | test_msg("Unexpected compress type, wanted %d, got %d\n", | ||
670 | BTRFS_COMPRESS_ZLIB, em->compress_type); | ||
671 | goto out; | ||
672 | } | ||
673 | disk_bytenr = em->block_start; | ||
674 | orig_start = em->start; | ||
675 | offset = em->start + em->len; | ||
676 | free_extent_map(em); | ||
677 | |||
678 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | ||
679 | if (IS_ERR(em)) { | ||
680 | test_msg("Got an error when we shouldn't have\n"); | ||
681 | goto out; | ||
682 | } | ||
683 | if (em->block_start >= EXTENT_MAP_LAST_BYTE) { | ||
684 | test_msg("Expected a real extent, got %llu\n", em->block_start); | ||
685 | goto out; | ||
686 | } | ||
687 | if (em->start != offset || em->len != 4096) { | ||
688 | test_msg("Unexpected extent wanted start %llu len 4096, got " | ||
689 | "start %llu len %llu\n", offset, em->start, em->len); | ||
690 | goto out; | ||
691 | } | ||
692 | if (em->flags != 0) { | ||
693 | test_msg("Unexpected flags set, want 0 have %lu\n", em->flags); | ||
694 | goto out; | ||
695 | } | ||
696 | if (em->orig_start != em->start) { | ||
697 | test_msg("Wrong orig offset, want %llu, have %llu\n", em->start, | ||
698 | em->orig_start); | ||
699 | goto out; | ||
700 | } | ||
701 | offset = em->start + em->len; | ||
702 | free_extent_map(em); | ||
703 | |||
704 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | ||
705 | if (IS_ERR(em)) { | ||
706 | test_msg("Got an error when we shouldn't have\n"); | ||
707 | goto out; | ||
708 | } | ||
709 | if (em->block_start != disk_bytenr) { | ||
710 | test_msg("Block start does not match, want %llu got %llu\n", | ||
711 | disk_bytenr, em->block_start); | ||
712 | goto out; | ||
713 | } | ||
714 | if (em->start != offset || em->len != 8192) { | ||
715 | test_msg("Unexpected extent wanted start %llu len 8192, got " | ||
716 | "start %llu len %llu\n", offset, em->start, em->len); | ||
717 | goto out; | ||
718 | } | ||
719 | if (em->flags != compressed_only) { | ||
720 | test_msg("Unexpected flags set, want %lu have %lu\n", | ||
721 | compressed_only, em->flags); | ||
722 | goto out; | ||
723 | } | ||
724 | if (em->orig_start != orig_start) { | ||
725 | test_msg("Wrong orig offset, want %llu, have %llu\n", | ||
726 | em->start, orig_start); | ||
727 | goto out; | ||
728 | } | ||
729 | if (em->compress_type != BTRFS_COMPRESS_ZLIB) { | ||
730 | test_msg("Unexpected compress type, wanted %d, got %d\n", | ||
731 | BTRFS_COMPRESS_ZLIB, em->compress_type); | ||
732 | goto out; | ||
733 | } | ||
734 | offset = em->start + em->len; | ||
735 | free_extent_map(em); | ||
736 | |||
737 | /* A hole between regular extents but no hole extent */ | ||
738 | em = btrfs_get_extent(inode, NULL, 0, offset + 6, 4096, 0); | ||
739 | if (IS_ERR(em)) { | ||
740 | test_msg("Got an error when we shouldn't have\n"); | ||
741 | goto out; | ||
742 | } | ||
743 | if (em->block_start >= EXTENT_MAP_LAST_BYTE) { | ||
744 | test_msg("Expected a real extent, got %llu\n", em->block_start); | ||
745 | goto out; | ||
746 | } | ||
747 | if (em->start != offset || em->len != 4096) { | ||
748 | test_msg("Unexpected extent wanted start %llu len 4096, got " | ||
749 | "start %llu len %llu\n", offset, em->start, em->len); | ||
750 | goto out; | ||
751 | } | ||
752 | if (em->flags != 0) { | ||
753 | test_msg("Unexpected flags set, want 0 have %lu\n", em->flags); | ||
754 | goto out; | ||
755 | } | ||
756 | if (em->orig_start != em->start) { | ||
757 | test_msg("Wrong orig offset, want %llu, have %llu\n", em->start, | ||
758 | em->orig_start); | ||
759 | goto out; | ||
760 | } | ||
761 | offset = em->start + em->len; | ||
762 | free_extent_map(em); | ||
763 | |||
764 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096 * 1024, 0); | ||
765 | if (IS_ERR(em)) { | ||
766 | test_msg("Got an error when we shouldn't have\n"); | ||
767 | goto out; | ||
768 | } | ||
769 | if (em->block_start != EXTENT_MAP_HOLE) { | ||
770 | test_msg("Expected a hole extent, got %llu\n", em->block_start); | ||
771 | goto out; | ||
772 | } | ||
773 | /* | ||
774 | * Currently we just return a length that we requested rather than the | ||
775 | * length of the actual hole, if this changes we'll have to change this | ||
776 | * test. | ||
777 | */ | ||
778 | if (em->start != offset || em->len != 12288) { | ||
779 | test_msg("Unexpected extent wanted start %llu len 12288, got " | ||
780 | "start %llu len %llu\n", offset, em->start, em->len); | ||
781 | goto out; | ||
782 | } | ||
783 | if (em->flags != vacancy_only) { | ||
784 | test_msg("Unexpected flags set, want %lu have %lu\n", | ||
785 | vacancy_only, em->flags); | ||
786 | goto out; | ||
787 | } | ||
788 | if (em->orig_start != em->start) { | ||
789 | test_msg("Wrong orig offset, want %llu, have %llu\n", em->start, | ||
790 | em->orig_start); | ||
791 | goto out; | ||
792 | } | ||
793 | offset = em->start + em->len; | ||
794 | free_extent_map(em); | ||
795 | |||
796 | em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0); | ||
797 | if (IS_ERR(em)) { | ||
798 | test_msg("Got an error when we shouldn't have\n"); | ||
799 | goto out; | ||
800 | } | ||
801 | if (em->block_start >= EXTENT_MAP_LAST_BYTE) { | ||
802 | test_msg("Expected a real extent, got %llu\n", em->block_start); | ||
803 | goto out; | ||
804 | } | ||
805 | if (em->start != offset || em->len != 4096) { | ||
806 | test_msg("Unexpected extent wanted start %llu len 4096, got " | ||
807 | "start %llu len %llu\n", offset, em->start, em->len); | ||
808 | goto out; | ||
809 | } | ||
810 | if (em->flags != 0) { | ||
811 | test_msg("Unexpected flags set, want 0 have %lu\n", em->flags); | ||
812 | goto out; | ||
813 | } | ||
814 | if (em->orig_start != em->start) { | ||
815 | test_msg("Wrong orig offset, want %llu, have %llu\n", em->start, | ||
816 | em->orig_start); | ||
817 | goto out; | ||
818 | } | ||
819 | ret = 0; | ||
820 | out: | ||
821 | if (!IS_ERR(em)) | ||
822 | free_extent_map(em); | ||
823 | iput(inode); | ||
824 | free_dummy_root(root); | ||
825 | return ret; | ||
826 | } | ||
827 | |||
828 | int btrfs_test_inodes(void) | ||
829 | { | ||
830 | test_msg("Running btrfs_get_extent tests\n"); | ||
831 | return test_btrfs_get_extent(); | ||
832 | } | ||