Commit | Line | Data |
---|---|---|
c1d7c514 | 1 | // SPDX-License-Identifier: GPL-2.0 |
dc11dd5d JB |
2 | /* |
3 | * Copyright (C) 2013 Fusion IO. All rights reserved. | |
dc11dd5d JB |
4 | */ |
5 | ||
6 | #include <linux/slab.h> | |
7 | #include "btrfs-tests.h" | |
8 | #include "../ctree.h" | |
d0bd4560 | 9 | #include "../disk-io.h" |
dc11dd5d | 10 | #include "../free-space-cache.h" |
aac0023c | 11 | #include "../block-group.h" |
dc11dd5d | 12 | |
0ef6447a | 13 | #define BITS_PER_BITMAP (PAGE_SIZE * 8UL) |
dc11dd5d JB |
14 | |
15 | /* | |
01327610 | 16 | * This test just does basic sanity checking, making sure we can add an extent |
dc11dd5d JB |
17 | * entry and remove space from either end and the middle, and make sure we can |
18 | * remove space that covers adjacent extent entries. | |
19 | */ | |
32da5386 | 20 | static int test_extents(struct btrfs_block_group *cache) |
dc11dd5d JB |
21 | { |
22 | int ret = 0; | |
23 | ||
315b76b4 | 24 | test_msg("running extent only tests"); |
dc11dd5d JB |
25 | |
26 | /* First just make sure we can remove an entire entry */ | |
ee22184b | 27 | ret = btrfs_add_free_space(cache, 0, SZ_4M); |
dc11dd5d | 28 | if (ret) { |
3c7251f2 | 29 | test_err("error adding initial extents %d", ret); |
dc11dd5d JB |
30 | return ret; |
31 | } | |
32 | ||
ee22184b | 33 | ret = btrfs_remove_free_space(cache, 0, SZ_4M); |
dc11dd5d | 34 | if (ret) { |
3c7251f2 | 35 | test_err("error removing extent %d", ret); |
dc11dd5d JB |
36 | return ret; |
37 | } | |
38 | ||
ee22184b | 39 | if (test_check_exists(cache, 0, SZ_4M)) { |
3c7251f2 | 40 | test_err("full remove left some lingering space"); |
dc11dd5d JB |
41 | return -1; |
42 | } | |
43 | ||
44 | /* Ok edge and middle cases now */ | |
ee22184b | 45 | ret = btrfs_add_free_space(cache, 0, SZ_4M); |
dc11dd5d | 46 | if (ret) { |
3c7251f2 | 47 | test_err("error adding half extent %d", ret); |
dc11dd5d JB |
48 | return ret; |
49 | } | |
50 | ||
ee22184b | 51 | ret = btrfs_remove_free_space(cache, 3 * SZ_1M, SZ_1M); |
dc11dd5d | 52 | if (ret) { |
3c7251f2 | 53 | test_err("error removing tail end %d", ret); |
dc11dd5d JB |
54 | return ret; |
55 | } | |
56 | ||
ee22184b | 57 | ret = btrfs_remove_free_space(cache, 0, SZ_1M); |
dc11dd5d | 58 | if (ret) { |
3c7251f2 | 59 | test_err("error removing front end %d", ret); |
dc11dd5d JB |
60 | return ret; |
61 | } | |
62 | ||
ee22184b | 63 | ret = btrfs_remove_free_space(cache, SZ_2M, 4096); |
dc11dd5d | 64 | if (ret) { |
3c7251f2 | 65 | test_err("error removing middle piece %d", ret); |
dc11dd5d JB |
66 | return ret; |
67 | } | |
68 | ||
ee22184b | 69 | if (test_check_exists(cache, 0, SZ_1M)) { |
3c7251f2 | 70 | test_err("still have space at the front"); |
dc11dd5d JB |
71 | return -1; |
72 | } | |
73 | ||
ee22184b | 74 | if (test_check_exists(cache, SZ_2M, 4096)) { |
3c7251f2 | 75 | test_err("still have space in the middle"); |
dc11dd5d JB |
76 | return -1; |
77 | } | |
78 | ||
ee22184b | 79 | if (test_check_exists(cache, 3 * SZ_1M, SZ_1M)) { |
3c7251f2 | 80 | test_err("still have space at the end"); |
dc11dd5d JB |
81 | return -1; |
82 | } | |
83 | ||
84 | /* Cleanup */ | |
fc80f7ac | 85 | btrfs_remove_free_space_cache(cache); |
dc11dd5d JB |
86 | |
87 | return 0; | |
88 | } | |
89 | ||
32da5386 | 90 | static int test_bitmaps(struct btrfs_block_group *cache, u32 sectorsize) |
dc11dd5d JB |
91 | { |
92 | u64 next_bitmap_offset; | |
93 | int ret; | |
94 | ||
315b76b4 | 95 | test_msg("running bitmap only tests"); |
dc11dd5d | 96 | |
ee22184b | 97 | ret = test_add_free_space_entry(cache, 0, SZ_4M, 1); |
dc11dd5d | 98 | if (ret) { |
3c7251f2 | 99 | test_err("couldn't create a bitmap entry %d", ret); |
dc11dd5d JB |
100 | return ret; |
101 | } | |
102 | ||
ee22184b | 103 | ret = btrfs_remove_free_space(cache, 0, SZ_4M); |
dc11dd5d | 104 | if (ret) { |
3c7251f2 | 105 | test_err("error removing bitmap full range %d", ret); |
dc11dd5d JB |
106 | return ret; |
107 | } | |
108 | ||
ee22184b | 109 | if (test_check_exists(cache, 0, SZ_4M)) { |
3c7251f2 | 110 | test_err("left some space in bitmap"); |
dc11dd5d JB |
111 | return -1; |
112 | } | |
113 | ||
ee22184b | 114 | ret = test_add_free_space_entry(cache, 0, SZ_4M, 1); |
dc11dd5d | 115 | if (ret) { |
3c7251f2 | 116 | test_err("couldn't add to our bitmap entry %d", ret); |
dc11dd5d JB |
117 | return ret; |
118 | } | |
119 | ||
ee22184b | 120 | ret = btrfs_remove_free_space(cache, SZ_1M, SZ_2M); |
dc11dd5d | 121 | if (ret) { |
3c7251f2 | 122 | test_err("couldn't remove middle chunk %d", ret); |
dc11dd5d JB |
123 | return ret; |
124 | } | |
125 | ||
126 | /* | |
127 | * The first bitmap we have starts at offset 0 so the next one is just | |
128 | * at the end of the first bitmap. | |
129 | */ | |
b9ef22de | 130 | next_bitmap_offset = (u64)(BITS_PER_BITMAP * sectorsize); |
dc11dd5d JB |
131 | |
132 | /* Test a bit straddling two bitmaps */ | |
ee22184b BL |
133 | ret = test_add_free_space_entry(cache, next_bitmap_offset - SZ_2M, |
134 | SZ_4M, 1); | |
dc11dd5d | 135 | if (ret) { |
3c7251f2 | 136 | test_err("couldn't add space that straddles two bitmaps %d", |
dc11dd5d JB |
137 | ret); |
138 | return ret; | |
139 | } | |
140 | ||
ee22184b | 141 | ret = btrfs_remove_free_space(cache, next_bitmap_offset - SZ_1M, SZ_2M); |
dc11dd5d | 142 | if (ret) { |
3c7251f2 | 143 | test_err("couldn't remove overlapping space %d", ret); |
dc11dd5d JB |
144 | return ret; |
145 | } | |
146 | ||
ee22184b | 147 | if (test_check_exists(cache, next_bitmap_offset - SZ_1M, SZ_2M)) { |
3c7251f2 | 148 | test_err("left some space when removing overlapping"); |
dc11dd5d JB |
149 | return -1; |
150 | } | |
151 | ||
fc80f7ac | 152 | btrfs_remove_free_space_cache(cache); |
dc11dd5d JB |
153 | |
154 | return 0; | |
155 | } | |
156 | ||
157 | /* This is the high grade jackassery */ | |
32da5386 | 158 | static int test_bitmaps_and_extents(struct btrfs_block_group *cache, |
b9ef22de | 159 | u32 sectorsize) |
dc11dd5d | 160 | { |
b9ef22de | 161 | u64 bitmap_offset = (u64)(BITS_PER_BITMAP * sectorsize); |
dc11dd5d JB |
162 | int ret; |
163 | ||
315b76b4 | 164 | test_msg("running bitmap and extent tests"); |
dc11dd5d JB |
165 | |
166 | /* | |
167 | * First let's do something simple, an extent at the same offset as the | |
168 | * bitmap, but the free space completely in the extent and then | |
169 | * completely in the bitmap. | |
170 | */ | |
ee22184b | 171 | ret = test_add_free_space_entry(cache, SZ_4M, SZ_1M, 1); |
dc11dd5d | 172 | if (ret) { |
3c7251f2 | 173 | test_err("couldn't create bitmap entry %d", ret); |
dc11dd5d JB |
174 | return ret; |
175 | } | |
176 | ||
ee22184b | 177 | ret = test_add_free_space_entry(cache, 0, SZ_1M, 0); |
dc11dd5d | 178 | if (ret) { |
3c7251f2 | 179 | test_err("couldn't add extent entry %d", ret); |
dc11dd5d JB |
180 | return ret; |
181 | } | |
182 | ||
ee22184b | 183 | ret = btrfs_remove_free_space(cache, 0, SZ_1M); |
dc11dd5d | 184 | if (ret) { |
3c7251f2 | 185 | test_err("couldn't remove extent entry %d", ret); |
dc11dd5d JB |
186 | return ret; |
187 | } | |
188 | ||
ee22184b | 189 | if (test_check_exists(cache, 0, SZ_1M)) { |
3c7251f2 | 190 | test_err("left remnants after our remove"); |
dc11dd5d JB |
191 | return -1; |
192 | } | |
193 | ||
194 | /* Now to add back the extent entry and remove from the bitmap */ | |
ee22184b | 195 | ret = test_add_free_space_entry(cache, 0, SZ_1M, 0); |
dc11dd5d | 196 | if (ret) { |
3c7251f2 | 197 | test_err("couldn't re-add extent entry %d", ret); |
dc11dd5d JB |
198 | return ret; |
199 | } | |
200 | ||
ee22184b | 201 | ret = btrfs_remove_free_space(cache, SZ_4M, SZ_1M); |
dc11dd5d | 202 | if (ret) { |
3c7251f2 | 203 | test_err("couldn't remove from bitmap %d", ret); |
dc11dd5d JB |
204 | return ret; |
205 | } | |
206 | ||
ee22184b | 207 | if (test_check_exists(cache, SZ_4M, SZ_1M)) { |
3c7251f2 | 208 | test_err("left remnants in the bitmap"); |
dc11dd5d JB |
209 | return -1; |
210 | } | |
211 | ||
212 | /* | |
213 | * Ok so a little more evil, extent entry and bitmap at the same offset, | |
214 | * removing an overlapping chunk. | |
215 | */ | |
ee22184b | 216 | ret = test_add_free_space_entry(cache, SZ_1M, SZ_4M, 1); |
dc11dd5d | 217 | if (ret) { |
3c7251f2 | 218 | test_err("couldn't add to a bitmap %d", ret); |
dc11dd5d JB |
219 | return ret; |
220 | } | |
221 | ||
ee22184b | 222 | ret = btrfs_remove_free_space(cache, SZ_512K, 3 * SZ_1M); |
dc11dd5d | 223 | if (ret) { |
3c7251f2 | 224 | test_err("couldn't remove overlapping space %d", ret); |
dc11dd5d JB |
225 | return ret; |
226 | } | |
227 | ||
ee22184b | 228 | if (test_check_exists(cache, SZ_512K, 3 * SZ_1M)) { |
3c7251f2 | 229 | test_err("left over pieces after removing overlapping"); |
dc11dd5d JB |
230 | return -1; |
231 | } | |
232 | ||
fc80f7ac | 233 | btrfs_remove_free_space_cache(cache); |
dc11dd5d JB |
234 | |
235 | /* Now with the extent entry offset into the bitmap */ | |
ee22184b | 236 | ret = test_add_free_space_entry(cache, SZ_4M, SZ_4M, 1); |
dc11dd5d | 237 | if (ret) { |
3c7251f2 | 238 | test_err("couldn't add space to the bitmap %d", ret); |
dc11dd5d JB |
239 | return ret; |
240 | } | |
241 | ||
ee22184b | 242 | ret = test_add_free_space_entry(cache, SZ_2M, SZ_2M, 0); |
dc11dd5d | 243 | if (ret) { |
3c7251f2 | 244 | test_err("couldn't add extent to the cache %d", ret); |
dc11dd5d JB |
245 | return ret; |
246 | } | |
247 | ||
ee22184b | 248 | ret = btrfs_remove_free_space(cache, 3 * SZ_1M, SZ_4M); |
dc11dd5d | 249 | if (ret) { |
3c7251f2 | 250 | test_err("problem removing overlapping space %d", ret); |
dc11dd5d JB |
251 | return ret; |
252 | } | |
253 | ||
ee22184b | 254 | if (test_check_exists(cache, 3 * SZ_1M, SZ_4M)) { |
3c7251f2 | 255 | test_err("left something behind when removing space"); |
dc11dd5d JB |
256 | return -1; |
257 | } | |
258 | ||
259 | /* | |
260 | * This has blown up in the past, the extent entry starts before the | |
261 | * bitmap entry, but we're trying to remove an offset that falls | |
262 | * completely within the bitmap range and is in both the extent entry | |
263 | * and the bitmap entry, looks like this | |
264 | * | |
265 | * [ extent ] | |
266 | * [ bitmap ] | |
267 | * [ del ] | |
268 | */ | |
fc80f7ac | 269 | btrfs_remove_free_space_cache(cache); |
ee22184b | 270 | ret = test_add_free_space_entry(cache, bitmap_offset + SZ_4M, SZ_4M, 1); |
dc11dd5d | 271 | if (ret) { |
3c7251f2 | 272 | test_err("couldn't add bitmap %d", ret); |
dc11dd5d JB |
273 | return ret; |
274 | } | |
275 | ||
ee22184b BL |
276 | ret = test_add_free_space_entry(cache, bitmap_offset - SZ_1M, |
277 | 5 * SZ_1M, 0); | |
dc11dd5d | 278 | if (ret) { |
3c7251f2 | 279 | test_err("couldn't add extent entry %d", ret); |
dc11dd5d JB |
280 | return ret; |
281 | } | |
282 | ||
ee22184b | 283 | ret = btrfs_remove_free_space(cache, bitmap_offset + SZ_1M, 5 * SZ_1M); |
dc11dd5d | 284 | if (ret) { |
3c7251f2 | 285 | test_err("failed to free our space %d", ret); |
dc11dd5d JB |
286 | return ret; |
287 | } | |
288 | ||
ee22184b | 289 | if (test_check_exists(cache, bitmap_offset + SZ_1M, 5 * SZ_1M)) { |
3c7251f2 | 290 | test_err("left stuff over"); |
dc11dd5d JB |
291 | return -1; |
292 | } | |
293 | ||
fc80f7ac | 294 | btrfs_remove_free_space_cache(cache); |
dc11dd5d JB |
295 | |
296 | /* | |
297 | * This blew up before, we have part of the free space in a bitmap and | |
298 | * then the entirety of the rest of the space in an extent. This used | |
299 | * to return -EAGAIN back from btrfs_remove_extent, make sure this | |
300 | * doesn't happen. | |
301 | */ | |
ee22184b | 302 | ret = test_add_free_space_entry(cache, SZ_1M, SZ_2M, 1); |
dc11dd5d | 303 | if (ret) { |
3c7251f2 | 304 | test_err("couldn't add bitmap entry %d", ret); |
dc11dd5d JB |
305 | return ret; |
306 | } | |
307 | ||
ee22184b | 308 | ret = test_add_free_space_entry(cache, 3 * SZ_1M, SZ_1M, 0); |
dc11dd5d | 309 | if (ret) { |
3c7251f2 | 310 | test_err("couldn't add extent entry %d", ret); |
dc11dd5d JB |
311 | return ret; |
312 | } | |
313 | ||
ee22184b | 314 | ret = btrfs_remove_free_space(cache, SZ_1M, 3 * SZ_1M); |
dc11dd5d | 315 | if (ret) { |
3c7251f2 | 316 | test_err("error removing bitmap and extent overlapping %d", ret); |
dc11dd5d JB |
317 | return ret; |
318 | } | |
319 | ||
fc80f7ac | 320 | btrfs_remove_free_space_cache(cache); |
dc11dd5d JB |
321 | return 0; |
322 | } | |
323 | ||
20005523 FM |
324 | /* Used by test_steal_space_from_bitmap_to_extent(). */ |
325 | static bool test_use_bitmap(struct btrfs_free_space_ctl *ctl, | |
326 | struct btrfs_free_space *info) | |
327 | { | |
328 | return ctl->free_extents > 0; | |
329 | } | |
330 | ||
331 | /* Used by test_steal_space_from_bitmap_to_extent(). */ | |
332 | static int | |
32da5386 | 333 | check_num_extents_and_bitmaps(const struct btrfs_block_group *cache, |
20005523 FM |
334 | const int num_extents, |
335 | const int num_bitmaps) | |
336 | { | |
337 | if (cache->free_space_ctl->free_extents != num_extents) { | |
3c7251f2 DS |
338 | test_err( |
339 | "incorrect # of extent entries in the cache: %d, expected %d", | |
20005523 FM |
340 | cache->free_space_ctl->free_extents, num_extents); |
341 | return -EINVAL; | |
342 | } | |
343 | if (cache->free_space_ctl->total_bitmaps != num_bitmaps) { | |
3c7251f2 DS |
344 | test_err( |
345 | "incorrect # of extent entries in the cache: %d, expected %d", | |
20005523 FM |
346 | cache->free_space_ctl->total_bitmaps, num_bitmaps); |
347 | return -EINVAL; | |
348 | } | |
349 | return 0; | |
350 | } | |
351 | ||
352 | /* Used by test_steal_space_from_bitmap_to_extent(). */ | |
32da5386 | 353 | static int check_cache_empty(struct btrfs_block_group *cache) |
20005523 FM |
354 | { |
355 | u64 offset; | |
356 | u64 max_extent_size; | |
357 | ||
358 | /* | |
359 | * Now lets confirm that there's absolutely no free space left to | |
360 | * allocate. | |
361 | */ | |
362 | if (cache->free_space_ctl->free_space != 0) { | |
3c7251f2 | 363 | test_err("cache free space is not 0"); |
20005523 FM |
364 | return -EINVAL; |
365 | } | |
366 | ||
367 | /* And any allocation request, no matter how small, should fail now. */ | |
368 | offset = btrfs_find_space_for_alloc(cache, 0, 4096, 0, | |
369 | &max_extent_size); | |
370 | if (offset != 0) { | |
3c7251f2 | 371 | test_err("space allocation did not fail, returned offset: %llu", |
20005523 FM |
372 | offset); |
373 | return -EINVAL; | |
374 | } | |
375 | ||
376 | /* And no extent nor bitmap entries in the cache anymore. */ | |
377 | return check_num_extents_and_bitmaps(cache, 0, 0); | |
378 | } | |
379 | ||
380 | /* | |
381 | * Before we were able to steal free space from a bitmap entry to an extent | |
382 | * entry, we could end up with 2 entries representing a contiguous free space. | |
383 | * One would be an extent entry and the other a bitmap entry. Since in order | |
384 | * to allocate space to a caller we use only 1 entry, we couldn't return that | |
385 | * whole range to the caller if it was requested. This forced the caller to | |
386 | * either assume ENOSPC or perform several smaller space allocations, which | |
387 | * wasn't optimal as they could be spread all over the block group while under | |
388 | * concurrency (extra overhead and fragmentation). | |
389 | * | |
01327610 NS |
390 | * This stealing approach is beneficial, since we always prefer to allocate |
391 | * from extent entries, both for clustered and non-clustered allocation | |
392 | * requests. | |
20005523 FM |
393 | */ |
394 | static int | |
32da5386 | 395 | test_steal_space_from_bitmap_to_extent(struct btrfs_block_group *cache, |
b9ef22de | 396 | u32 sectorsize) |
20005523 FM |
397 | { |
398 | int ret; | |
399 | u64 offset; | |
400 | u64 max_extent_size; | |
20e5506b | 401 | const struct btrfs_free_space_op test_free_space_ops = { |
28f0779a DS |
402 | .use_bitmap = test_use_bitmap, |
403 | }; | |
20e5506b | 404 | const struct btrfs_free_space_op *orig_free_space_ops; |
20005523 | 405 | |
e4fa7469 | 406 | test_msg("running space stealing from bitmap to extent tests"); |
20005523 FM |
407 | |
408 | /* | |
409 | * For this test, we want to ensure we end up with an extent entry | |
410 | * immediately adjacent to a bitmap entry, where the bitmap starts | |
411 | * at an offset where the extent entry ends. We keep adding and | |
412 | * removing free space to reach into this state, but to get there | |
413 | * we need to reach a point where marking new free space doesn't | |
414 | * result in adding new extent entries or merging the new space | |
415 | * with existing extent entries - the space ends up being marked | |
416 | * in an existing bitmap that covers the new free space range. | |
417 | * | |
418 | * To get there, we need to reach the threshold defined set at | |
419 | * cache->free_space_ctl->extents_thresh, which currently is | |
420 | * 256 extents on a x86_64 system at least, and a few other | |
421 | * conditions (check free_space_cache.c). Instead of making the | |
422 | * test much longer and complicated, use a "use_bitmap" operation | |
423 | * that forces use of bitmaps as soon as we have at least 1 | |
424 | * extent entry. | |
425 | */ | |
28f0779a DS |
426 | orig_free_space_ops = cache->free_space_ctl->op; |
427 | cache->free_space_ctl->op = &test_free_space_ops; | |
20005523 FM |
428 | |
429 | /* | |
430 | * Extent entry covering free space range [128Mb - 256Kb, 128Mb - 128Kb[ | |
431 | */ | |
ee22184b | 432 | ret = test_add_free_space_entry(cache, SZ_128M - SZ_256K, SZ_128K, 0); |
20005523 | 433 | if (ret) { |
3c7251f2 | 434 | test_err("couldn't add extent entry %d", ret); |
20005523 FM |
435 | return ret; |
436 | } | |
437 | ||
438 | /* Bitmap entry covering free space range [128Mb + 512Kb, 256Mb[ */ | |
ee22184b BL |
439 | ret = test_add_free_space_entry(cache, SZ_128M + SZ_512K, |
440 | SZ_128M - SZ_512K, 1); | |
20005523 | 441 | if (ret) { |
3c7251f2 | 442 | test_err("couldn't add bitmap entry %d", ret); |
20005523 FM |
443 | return ret; |
444 | } | |
445 | ||
446 | ret = check_num_extents_and_bitmaps(cache, 2, 1); | |
447 | if (ret) | |
448 | return ret; | |
449 | ||
450 | /* | |
451 | * Now make only the first 256Kb of the bitmap marked as free, so that | |
452 | * we end up with only the following ranges marked as free space: | |
453 | * | |
454 | * [128Mb - 256Kb, 128Mb - 128Kb[ | |
455 | * [128Mb + 512Kb, 128Mb + 768Kb[ | |
456 | */ | |
457 | ret = btrfs_remove_free_space(cache, | |
ee22184b BL |
458 | SZ_128M + 768 * SZ_1K, |
459 | SZ_128M - 768 * SZ_1K); | |
20005523 | 460 | if (ret) { |
3c7251f2 | 461 | test_err("failed to free part of bitmap space %d", ret); |
20005523 FM |
462 | return ret; |
463 | } | |
464 | ||
465 | /* Confirm that only those 2 ranges are marked as free. */ | |
ee22184b | 466 | if (!test_check_exists(cache, SZ_128M - SZ_256K, SZ_128K)) { |
3c7251f2 | 467 | test_err("free space range missing"); |
20005523 FM |
468 | return -ENOENT; |
469 | } | |
ee22184b | 470 | if (!test_check_exists(cache, SZ_128M + SZ_512K, SZ_256K)) { |
3c7251f2 | 471 | test_err("free space range missing"); |
20005523 FM |
472 | return -ENOENT; |
473 | } | |
474 | ||
475 | /* | |
476 | * Confirm that the bitmap range [128Mb + 768Kb, 256Mb[ isn't marked | |
477 | * as free anymore. | |
478 | */ | |
ee22184b BL |
479 | if (test_check_exists(cache, SZ_128M + 768 * SZ_1K, |
480 | SZ_128M - 768 * SZ_1K)) { | |
3c7251f2 | 481 | test_err("bitmap region not removed from space cache"); |
20005523 FM |
482 | return -EINVAL; |
483 | } | |
484 | ||
485 | /* | |
486 | * Confirm that the region [128Mb + 256Kb, 128Mb + 512Kb[, which is | |
487 | * covered by the bitmap, isn't marked as free. | |
488 | */ | |
ee22184b | 489 | if (test_check_exists(cache, SZ_128M + SZ_256K, SZ_256K)) { |
3c7251f2 | 490 | test_err("invalid bitmap region marked as free"); |
20005523 FM |
491 | return -EINVAL; |
492 | } | |
493 | ||
494 | /* | |
495 | * Confirm that the region [128Mb, 128Mb + 256Kb[, which is covered | |
496 | * by the bitmap too, isn't marked as free either. | |
497 | */ | |
ee22184b | 498 | if (test_check_exists(cache, SZ_128M, SZ_256K)) { |
3c7251f2 | 499 | test_err("invalid bitmap region marked as free"); |
20005523 FM |
500 | return -EINVAL; |
501 | } | |
502 | ||
503 | /* | |
504 | * Now lets mark the region [128Mb, 128Mb + 512Kb[ as free too. But, | |
505 | * lets make sure the free space cache marks it as free in the bitmap, | |
506 | * and doesn't insert a new extent entry to represent this region. | |
507 | */ | |
ee22184b | 508 | ret = btrfs_add_free_space(cache, SZ_128M, SZ_512K); |
20005523 | 509 | if (ret) { |
3c7251f2 | 510 | test_err("error adding free space: %d", ret); |
20005523 FM |
511 | return ret; |
512 | } | |
513 | /* Confirm the region is marked as free. */ | |
ee22184b | 514 | if (!test_check_exists(cache, SZ_128M, SZ_512K)) { |
3c7251f2 | 515 | test_err("bitmap region not marked as free"); |
20005523 FM |
516 | return -ENOENT; |
517 | } | |
518 | ||
519 | /* | |
520 | * Confirm that no new extent entries or bitmap entries were added to | |
521 | * the cache after adding that free space region. | |
522 | */ | |
523 | ret = check_num_extents_and_bitmaps(cache, 2, 1); | |
524 | if (ret) | |
525 | return ret; | |
526 | ||
527 | /* | |
528 | * Now lets add a small free space region to the right of the previous | |
529 | * one, which is not contiguous with it and is part of the bitmap too. | |
530 | * The goal is to test that the bitmap entry space stealing doesn't | |
531 | * steal this space region. | |
532 | */ | |
b9ef22de | 533 | ret = btrfs_add_free_space(cache, SZ_128M + SZ_16M, sectorsize); |
20005523 | 534 | if (ret) { |
3c7251f2 | 535 | test_err("error adding free space: %d", ret); |
20005523 FM |
536 | return ret; |
537 | } | |
538 | ||
539 | /* | |
540 | * Confirm that no new extent entries or bitmap entries were added to | |
541 | * the cache after adding that free space region. | |
542 | */ | |
543 | ret = check_num_extents_and_bitmaps(cache, 2, 1); | |
544 | if (ret) | |
545 | return ret; | |
546 | ||
547 | /* | |
548 | * Now mark the region [128Mb - 128Kb, 128Mb[ as free too. This will | |
549 | * expand the range covered by the existing extent entry that represents | |
550 | * the free space [128Mb - 256Kb, 128Mb - 128Kb[. | |
551 | */ | |
ee22184b | 552 | ret = btrfs_add_free_space(cache, SZ_128M - SZ_128K, SZ_128K); |
20005523 | 553 | if (ret) { |
3c7251f2 | 554 | test_err("error adding free space: %d", ret); |
20005523 FM |
555 | return ret; |
556 | } | |
557 | /* Confirm the region is marked as free. */ | |
ee22184b | 558 | if (!test_check_exists(cache, SZ_128M - SZ_128K, SZ_128K)) { |
3c7251f2 | 559 | test_err("extent region not marked as free"); |
20005523 FM |
560 | return -ENOENT; |
561 | } | |
562 | ||
563 | /* | |
564 | * Confirm that our extent entry didn't stole all free space from the | |
565 | * bitmap, because of the small 4Kb free space region. | |
566 | */ | |
567 | ret = check_num_extents_and_bitmaps(cache, 2, 1); | |
568 | if (ret) | |
569 | return ret; | |
570 | ||
571 | /* | |
572 | * So now we have the range [128Mb - 256Kb, 128Mb + 768Kb[ as free | |
573 | * space. Without stealing bitmap free space into extent entry space, | |
574 | * we would have all this free space represented by 2 entries in the | |
575 | * cache: | |
576 | * | |
577 | * extent entry covering range: [128Mb - 256Kb, 128Mb[ | |
578 | * bitmap entry covering range: [128Mb, 128Mb + 768Kb[ | |
579 | * | |
580 | * Attempting to allocate the whole free space (1Mb) would fail, because | |
581 | * we can't allocate from multiple entries. | |
582 | * With the bitmap free space stealing, we get a single extent entry | |
583 | * that represents the 1Mb free space, and therefore we're able to | |
584 | * allocate the whole free space at once. | |
585 | */ | |
ee22184b | 586 | if (!test_check_exists(cache, SZ_128M - SZ_256K, SZ_1M)) { |
3c7251f2 | 587 | test_err("expected region not marked as free"); |
20005523 FM |
588 | return -ENOENT; |
589 | } | |
590 | ||
b9ef22de | 591 | if (cache->free_space_ctl->free_space != (SZ_1M + sectorsize)) { |
3c7251f2 | 592 | test_err("cache free space is not 1Mb + %u", sectorsize); |
20005523 FM |
593 | return -EINVAL; |
594 | } | |
595 | ||
596 | offset = btrfs_find_space_for_alloc(cache, | |
ee22184b | 597 | 0, SZ_1M, 0, |
20005523 | 598 | &max_extent_size); |
ee22184b | 599 | if (offset != (SZ_128M - SZ_256K)) { |
3c7251f2 DS |
600 | test_err( |
601 | "failed to allocate 1Mb from space cache, returned offset is: %llu", | |
20005523 FM |
602 | offset); |
603 | return -EINVAL; | |
604 | } | |
605 | ||
b9ef22de FX |
606 | /* |
607 | * All that remains is a sectorsize free space region in a bitmap. | |
608 | * Confirm. | |
609 | */ | |
20005523 FM |
610 | ret = check_num_extents_and_bitmaps(cache, 1, 1); |
611 | if (ret) | |
612 | return ret; | |
613 | ||
b9ef22de | 614 | if (cache->free_space_ctl->free_space != sectorsize) { |
3c7251f2 | 615 | test_err("cache free space is not %u", sectorsize); |
20005523 FM |
616 | return -EINVAL; |
617 | } | |
618 | ||
619 | offset = btrfs_find_space_for_alloc(cache, | |
b9ef22de | 620 | 0, sectorsize, 0, |
20005523 | 621 | &max_extent_size); |
ee22184b | 622 | if (offset != (SZ_128M + SZ_16M)) { |
3c7251f2 | 623 | test_err("failed to allocate %u, returned offset : %llu", |
b9ef22de | 624 | sectorsize, offset); |
20005523 FM |
625 | return -EINVAL; |
626 | } | |
627 | ||
628 | ret = check_cache_empty(cache); | |
629 | if (ret) | |
630 | return ret; | |
631 | ||
fc80f7ac | 632 | btrfs_remove_free_space_cache(cache); |
20005523 FM |
633 | |
634 | /* | |
635 | * Now test a similar scenario, but where our extent entry is located | |
636 | * to the right of the bitmap entry, so that we can check that stealing | |
637 | * space from a bitmap to the front of an extent entry works. | |
638 | */ | |
639 | ||
640 | /* | |
641 | * Extent entry covering free space range [128Mb + 128Kb, 128Mb + 256Kb[ | |
642 | */ | |
ee22184b | 643 | ret = test_add_free_space_entry(cache, SZ_128M + SZ_128K, SZ_128K, 0); |
20005523 | 644 | if (ret) { |
3c7251f2 | 645 | test_err("couldn't add extent entry %d", ret); |
20005523 FM |
646 | return ret; |
647 | } | |
648 | ||
649 | /* Bitmap entry covering free space range [0, 128Mb - 512Kb[ */ | |
ee22184b | 650 | ret = test_add_free_space_entry(cache, 0, SZ_128M - SZ_512K, 1); |
20005523 | 651 | if (ret) { |
3c7251f2 | 652 | test_err("couldn't add bitmap entry %d", ret); |
20005523 FM |
653 | return ret; |
654 | } | |
655 | ||
656 | ret = check_num_extents_and_bitmaps(cache, 2, 1); | |
657 | if (ret) | |
658 | return ret; | |
659 | ||
660 | /* | |
661 | * Now make only the last 256Kb of the bitmap marked as free, so that | |
662 | * we end up with only the following ranges marked as free space: | |
663 | * | |
664 | * [128Mb + 128b, 128Mb + 256Kb[ | |
665 | * [128Mb - 768Kb, 128Mb - 512Kb[ | |
666 | */ | |
ee22184b | 667 | ret = btrfs_remove_free_space(cache, 0, SZ_128M - 768 * SZ_1K); |
20005523 | 668 | if (ret) { |
3c7251f2 | 669 | test_err("failed to free part of bitmap space %d", ret); |
20005523 FM |
670 | return ret; |
671 | } | |
672 | ||
673 | /* Confirm that only those 2 ranges are marked as free. */ | |
ee22184b | 674 | if (!test_check_exists(cache, SZ_128M + SZ_128K, SZ_128K)) { |
3c7251f2 | 675 | test_err("free space range missing"); |
20005523 FM |
676 | return -ENOENT; |
677 | } | |
ee22184b | 678 | if (!test_check_exists(cache, SZ_128M - 768 * SZ_1K, SZ_256K)) { |
3c7251f2 | 679 | test_err("free space range missing"); |
20005523 FM |
680 | return -ENOENT; |
681 | } | |
682 | ||
683 | /* | |
684 | * Confirm that the bitmap range [0, 128Mb - 768Kb[ isn't marked | |
685 | * as free anymore. | |
686 | */ | |
ee22184b | 687 | if (test_check_exists(cache, 0, SZ_128M - 768 * SZ_1K)) { |
3c7251f2 | 688 | test_err("bitmap region not removed from space cache"); |
20005523 FM |
689 | return -EINVAL; |
690 | } | |
691 | ||
692 | /* | |
693 | * Confirm that the region [128Mb - 512Kb, 128Mb[, which is | |
694 | * covered by the bitmap, isn't marked as free. | |
695 | */ | |
ee22184b | 696 | if (test_check_exists(cache, SZ_128M - SZ_512K, SZ_512K)) { |
3c7251f2 | 697 | test_err("invalid bitmap region marked as free"); |
20005523 FM |
698 | return -EINVAL; |
699 | } | |
700 | ||
701 | /* | |
702 | * Now lets mark the region [128Mb - 512Kb, 128Mb[ as free too. But, | |
703 | * lets make sure the free space cache marks it as free in the bitmap, | |
704 | * and doesn't insert a new extent entry to represent this region. | |
705 | */ | |
ee22184b | 706 | ret = btrfs_add_free_space(cache, SZ_128M - SZ_512K, SZ_512K); |
20005523 | 707 | if (ret) { |
3c7251f2 | 708 | test_err("error adding free space: %d", ret); |
20005523 FM |
709 | return ret; |
710 | } | |
711 | /* Confirm the region is marked as free. */ | |
ee22184b | 712 | if (!test_check_exists(cache, SZ_128M - SZ_512K, SZ_512K)) { |
3c7251f2 | 713 | test_err("bitmap region not marked as free"); |
20005523 FM |
714 | return -ENOENT; |
715 | } | |
716 | ||
717 | /* | |
718 | * Confirm that no new extent entries or bitmap entries were added to | |
719 | * the cache after adding that free space region. | |
720 | */ | |
721 | ret = check_num_extents_and_bitmaps(cache, 2, 1); | |
722 | if (ret) | |
723 | return ret; | |
724 | ||
725 | /* | |
726 | * Now lets add a small free space region to the left of the previous | |
727 | * one, which is not contiguous with it and is part of the bitmap too. | |
728 | * The goal is to test that the bitmap entry space stealing doesn't | |
729 | * steal this space region. | |
730 | */ | |
b9ef22de | 731 | ret = btrfs_add_free_space(cache, SZ_32M, 2 * sectorsize); |
20005523 | 732 | if (ret) { |
3c7251f2 | 733 | test_err("error adding free space: %d", ret); |
20005523 FM |
734 | return ret; |
735 | } | |
736 | ||
737 | /* | |
738 | * Now mark the region [128Mb, 128Mb + 128Kb[ as free too. This will | |
739 | * expand the range covered by the existing extent entry that represents | |
740 | * the free space [128Mb + 128Kb, 128Mb + 256Kb[. | |
741 | */ | |
ee22184b | 742 | ret = btrfs_add_free_space(cache, SZ_128M, SZ_128K); |
20005523 | 743 | if (ret) { |
3c7251f2 | 744 | test_err("error adding free space: %d", ret); |
20005523 FM |
745 | return ret; |
746 | } | |
747 | /* Confirm the region is marked as free. */ | |
ee22184b | 748 | if (!test_check_exists(cache, SZ_128M, SZ_128K)) { |
3c7251f2 | 749 | test_err("extent region not marked as free"); |
20005523 FM |
750 | return -ENOENT; |
751 | } | |
752 | ||
753 | /* | |
754 | * Confirm that our extent entry didn't stole all free space from the | |
b9ef22de | 755 | * bitmap, because of the small 2 * sectorsize free space region. |
20005523 FM |
756 | */ |
757 | ret = check_num_extents_and_bitmaps(cache, 2, 1); | |
758 | if (ret) | |
759 | return ret; | |
760 | ||
761 | /* | |
762 | * So now we have the range [128Mb - 768Kb, 128Mb + 256Kb[ as free | |
763 | * space. Without stealing bitmap free space into extent entry space, | |
764 | * we would have all this free space represented by 2 entries in the | |
765 | * cache: | |
766 | * | |
767 | * extent entry covering range: [128Mb, 128Mb + 256Kb[ | |
768 | * bitmap entry covering range: [128Mb - 768Kb, 128Mb[ | |
769 | * | |
770 | * Attempting to allocate the whole free space (1Mb) would fail, because | |
771 | * we can't allocate from multiple entries. | |
772 | * With the bitmap free space stealing, we get a single extent entry | |
773 | * that represents the 1Mb free space, and therefore we're able to | |
774 | * allocate the whole free space at once. | |
775 | */ | |
ee22184b | 776 | if (!test_check_exists(cache, SZ_128M - 768 * SZ_1K, SZ_1M)) { |
3c7251f2 | 777 | test_err("expected region not marked as free"); |
20005523 FM |
778 | return -ENOENT; |
779 | } | |
780 | ||
b9ef22de | 781 | if (cache->free_space_ctl->free_space != (SZ_1M + 2 * sectorsize)) { |
3c7251f2 | 782 | test_err("cache free space is not 1Mb + %u", 2 * sectorsize); |
20005523 FM |
783 | return -EINVAL; |
784 | } | |
785 | ||
ee22184b | 786 | offset = btrfs_find_space_for_alloc(cache, 0, SZ_1M, 0, |
20005523 | 787 | &max_extent_size); |
ee22184b | 788 | if (offset != (SZ_128M - 768 * SZ_1K)) { |
3c7251f2 DS |
789 | test_err( |
790 | "failed to allocate 1Mb from space cache, returned offset is: %llu", | |
20005523 FM |
791 | offset); |
792 | return -EINVAL; | |
793 | } | |
794 | ||
b9ef22de FX |
795 | /* |
796 | * All that remains is 2 * sectorsize free space region | |
797 | * in a bitmap. Confirm. | |
798 | */ | |
20005523 FM |
799 | ret = check_num_extents_and_bitmaps(cache, 1, 1); |
800 | if (ret) | |
801 | return ret; | |
802 | ||
b9ef22de | 803 | if (cache->free_space_ctl->free_space != 2 * sectorsize) { |
3c7251f2 | 804 | test_err("cache free space is not %u", 2 * sectorsize); |
20005523 FM |
805 | return -EINVAL; |
806 | } | |
807 | ||
808 | offset = btrfs_find_space_for_alloc(cache, | |
b9ef22de | 809 | 0, 2 * sectorsize, 0, |
20005523 | 810 | &max_extent_size); |
ee22184b | 811 | if (offset != SZ_32M) { |
3c7251f2 DS |
812 | test_err("failed to allocate %u, offset: %llu", |
813 | 2 * sectorsize, offset); | |
20005523 FM |
814 | return -EINVAL; |
815 | } | |
816 | ||
817 | ret = check_cache_empty(cache); | |
818 | if (ret) | |
819 | return ret; | |
820 | ||
28f0779a | 821 | cache->free_space_ctl->op = orig_free_space_ops; |
fc80f7ac | 822 | btrfs_remove_free_space_cache(cache); |
20005523 FM |
823 | |
824 | return 0; | |
825 | } | |
826 | ||
bbf27275 JB |
827 | static bool bytes_index_use_bitmap(struct btrfs_free_space_ctl *ctl, |
828 | struct btrfs_free_space *info) | |
829 | { | |
830 | return true; | |
831 | } | |
832 | ||
833 | static int test_bytes_index(struct btrfs_block_group *cache, u32 sectorsize) | |
834 | { | |
835 | const struct btrfs_free_space_op test_free_space_ops = { | |
836 | .use_bitmap = bytes_index_use_bitmap, | |
837 | }; | |
838 | const struct btrfs_free_space_op *orig_free_space_ops; | |
839 | struct btrfs_free_space_ctl *ctl = cache->free_space_ctl; | |
840 | struct btrfs_free_space *entry; | |
841 | struct rb_node *node; | |
842 | u64 offset, max_extent_size, bytes; | |
843 | int ret, i; | |
844 | ||
845 | test_msg("running bytes index tests"); | |
846 | ||
847 | /* First just validate that it does everything in order. */ | |
848 | offset = 0; | |
849 | for (i = 0; i < 10; i++) { | |
850 | bytes = (i + 1) * SZ_1M; | |
851 | ret = test_add_free_space_entry(cache, offset, bytes, 0); | |
852 | if (ret) { | |
853 | test_err("couldn't add extent entry %d\n", ret); | |
854 | return ret; | |
855 | } | |
856 | offset += bytes + sectorsize; | |
857 | } | |
858 | ||
859 | for (node = rb_first_cached(&ctl->free_space_bytes), i = 9; node; | |
860 | node = rb_next(node), i--) { | |
861 | entry = rb_entry(node, struct btrfs_free_space, bytes_index); | |
862 | bytes = (i + 1) * SZ_1M; | |
863 | if (entry->bytes != bytes) { | |
864 | test_err("invalid bytes index order, found %llu expected %llu", | |
865 | entry->bytes, bytes); | |
866 | return -EINVAL; | |
867 | } | |
868 | } | |
869 | ||
870 | /* Now validate bitmaps do the correct thing. */ | |
fc80f7ac | 871 | btrfs_remove_free_space_cache(cache); |
bbf27275 JB |
872 | for (i = 0; i < 2; i++) { |
873 | offset = i * BITS_PER_BITMAP * sectorsize; | |
874 | bytes = (i + 1) * SZ_1M; | |
875 | ret = test_add_free_space_entry(cache, offset, bytes, 1); | |
876 | if (ret) { | |
877 | test_err("couldn't add bitmap entry"); | |
878 | return ret; | |
879 | } | |
880 | } | |
881 | ||
882 | for (node = rb_first_cached(&ctl->free_space_bytes), i = 1; node; | |
883 | node = rb_next(node), i--) { | |
884 | entry = rb_entry(node, struct btrfs_free_space, bytes_index); | |
885 | bytes = (i + 1) * SZ_1M; | |
886 | if (entry->bytes != bytes) { | |
887 | test_err("invalid bytes index order, found %llu expected %llu", | |
888 | entry->bytes, bytes); | |
889 | return -EINVAL; | |
890 | } | |
891 | } | |
892 | ||
893 | /* Now validate bitmaps with different ->max_extent_size. */ | |
fc80f7ac | 894 | btrfs_remove_free_space_cache(cache); |
bbf27275 JB |
895 | orig_free_space_ops = cache->free_space_ctl->op; |
896 | cache->free_space_ctl->op = &test_free_space_ops; | |
897 | ||
898 | ret = test_add_free_space_entry(cache, 0, sectorsize, 1); | |
899 | if (ret) { | |
900 | test_err("couldn't add bitmap entry"); | |
901 | return ret; | |
902 | } | |
903 | ||
904 | offset = BITS_PER_BITMAP * sectorsize; | |
905 | ret = test_add_free_space_entry(cache, offset, sectorsize, 1); | |
906 | if (ret) { | |
907 | test_err("couldn't add bitmap_entry"); | |
908 | return ret; | |
909 | } | |
910 | ||
911 | /* | |
912 | * Now set a bunch of sectorsize extents in the first entry so it's | |
913 | * ->bytes is large. | |
914 | */ | |
915 | for (i = 2; i < 20; i += 2) { | |
916 | offset = sectorsize * i; | |
917 | ret = btrfs_add_free_space(cache, offset, sectorsize); | |
918 | if (ret) { | |
919 | test_err("error populating sparse bitmap %d", ret); | |
920 | return ret; | |
921 | } | |
922 | } | |
923 | ||
924 | /* | |
925 | * Now set a contiguous extent in the second bitmap so its | |
926 | * ->max_extent_size is larger than the first bitmaps. | |
927 | */ | |
928 | offset = (BITS_PER_BITMAP * sectorsize) + sectorsize; | |
929 | ret = btrfs_add_free_space(cache, offset, sectorsize); | |
930 | if (ret) { | |
931 | test_err("error adding contiguous extent %d", ret); | |
932 | return ret; | |
933 | } | |
934 | ||
935 | /* | |
936 | * Since we don't set ->max_extent_size unless we search everything | |
937 | * should be indexed on bytes. | |
938 | */ | |
939 | entry = rb_entry(rb_first_cached(&ctl->free_space_bytes), | |
940 | struct btrfs_free_space, bytes_index); | |
941 | if (entry->bytes != (10 * sectorsize)) { | |
942 | test_err("error, wrong entry in the first slot in bytes_index"); | |
943 | return -EINVAL; | |
944 | } | |
945 | ||
946 | max_extent_size = 0; | |
947 | offset = btrfs_find_space_for_alloc(cache, cache->start, sectorsize * 3, | |
948 | 0, &max_extent_size); | |
949 | if (offset != 0) { | |
950 | test_err("found space to alloc even though we don't have enough space"); | |
951 | return -EINVAL; | |
952 | } | |
953 | ||
954 | if (max_extent_size != (2 * sectorsize)) { | |
955 | test_err("got the wrong max_extent size %llu expected %llu", | |
956 | max_extent_size, (unsigned long long)(2 * sectorsize)); | |
957 | return -EINVAL; | |
958 | } | |
959 | ||
960 | /* | |
961 | * The search should have re-arranged the bytes index to use the | |
962 | * ->max_extent_size, validate it's now what we expect it to be. | |
963 | */ | |
964 | entry = rb_entry(rb_first_cached(&ctl->free_space_bytes), | |
965 | struct btrfs_free_space, bytes_index); | |
966 | if (entry->bytes != (2 * sectorsize)) { | |
967 | test_err("error, the bytes index wasn't recalculated properly"); | |
968 | return -EINVAL; | |
969 | } | |
970 | ||
971 | /* Add another sectorsize to re-arrange the tree back to ->bytes. */ | |
972 | offset = (BITS_PER_BITMAP * sectorsize) - sectorsize; | |
973 | ret = btrfs_add_free_space(cache, offset, sectorsize); | |
974 | if (ret) { | |
975 | test_err("error adding extent to the sparse entry %d", ret); | |
976 | return ret; | |
977 | } | |
978 | ||
979 | entry = rb_entry(rb_first_cached(&ctl->free_space_bytes), | |
980 | struct btrfs_free_space, bytes_index); | |
981 | if (entry->bytes != (11 * sectorsize)) { | |
982 | test_err("error, wrong entry in the first slot in bytes_index"); | |
983 | return -EINVAL; | |
984 | } | |
985 | ||
986 | /* | |
987 | * Now make sure we find our correct entry after searching that will | |
988 | * result in a re-arranging of the tree. | |
989 | */ | |
990 | max_extent_size = 0; | |
991 | offset = btrfs_find_space_for_alloc(cache, cache->start, sectorsize * 2, | |
992 | 0, &max_extent_size); | |
993 | if (offset != (BITS_PER_BITMAP * sectorsize)) { | |
994 | test_err("error, found %llu instead of %llu for our alloc", | |
995 | offset, | |
996 | (unsigned long long)(BITS_PER_BITMAP * sectorsize)); | |
997 | return -EINVAL; | |
998 | } | |
999 | ||
1000 | cache->free_space_ctl->op = orig_free_space_ops; | |
fc80f7ac | 1001 | btrfs_remove_free_space_cache(cache); |
bbf27275 JB |
1002 | return 0; |
1003 | } | |
1004 | ||
b9ef22de | 1005 | int btrfs_test_free_space_cache(u32 sectorsize, u32 nodesize) |
dc11dd5d | 1006 | { |
7c0260ee | 1007 | struct btrfs_fs_info *fs_info; |
32da5386 | 1008 | struct btrfs_block_group *cache; |
d0bd4560 JB |
1009 | struct btrfs_root *root = NULL; |
1010 | int ret = -ENOMEM; | |
dc11dd5d | 1011 | |
315b76b4 | 1012 | test_msg("running btrfs free space cache tests"); |
da17066c | 1013 | fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize); |
37b2a7bc DS |
1014 | if (!fs_info) { |
1015 | test_std_err(TEST_ALLOC_FS_INFO); | |
da17066c | 1016 | return -ENOMEM; |
37b2a7bc | 1017 | } |
dc11dd5d | 1018 | |
36b3dc05 FX |
1019 | /* |
1020 | * For ppc64 (with 64k page size), bytes per bitmap might be | |
1021 | * larger than 1G. To make bitmap test available in ppc64, | |
1022 | * alloc dummy block group whose size cross bitmaps. | |
1023 | */ | |
da17066c JM |
1024 | cache = btrfs_alloc_dummy_block_group(fs_info, |
1025 | BITS_PER_BITMAP * sectorsize + PAGE_SIZE); | |
dc11dd5d | 1026 | if (!cache) { |
3199366d | 1027 | test_std_err(TEST_ALLOC_BLOCK_GROUP); |
da17066c | 1028 | btrfs_free_dummy_fs_info(fs_info); |
dc11dd5d JB |
1029 | return 0; |
1030 | } | |
1031 | ||
da17066c | 1032 | root = btrfs_alloc_dummy_root(fs_info); |
7c0260ee | 1033 | if (IS_ERR(root)) { |
52ab7bca | 1034 | test_std_err(TEST_ALLOC_ROOT); |
7c0260ee | 1035 | ret = PTR_ERR(root); |
d0bd4560 | 1036 | goto out; |
7c0260ee | 1037 | } |
d0bd4560 | 1038 | |
abed4aaa JB |
1039 | root->root_key.objectid = BTRFS_EXTENT_TREE_OBJECTID; |
1040 | root->root_key.type = BTRFS_ROOT_ITEM_KEY; | |
1041 | root->root_key.offset = 0; | |
1042 | btrfs_global_root_insert(root); | |
d0bd4560 | 1043 | |
dc11dd5d JB |
1044 | ret = test_extents(cache); |
1045 | if (ret) | |
1046 | goto out; | |
b9ef22de | 1047 | ret = test_bitmaps(cache, sectorsize); |
dc11dd5d JB |
1048 | if (ret) |
1049 | goto out; | |
b9ef22de | 1050 | ret = test_bitmaps_and_extents(cache, sectorsize); |
dc11dd5d JB |
1051 | if (ret) |
1052 | goto out; | |
20005523 | 1053 | |
b9ef22de | 1054 | ret = test_steal_space_from_bitmap_to_extent(cache, sectorsize); |
bbf27275 JB |
1055 | if (ret) |
1056 | goto out; | |
1057 | ret = test_bytes_index(cache, sectorsize); | |
dc11dd5d | 1058 | out: |
7c55ee0c | 1059 | btrfs_free_dummy_block_group(cache); |
d0bd4560 | 1060 | btrfs_free_dummy_root(root); |
7c0260ee | 1061 | btrfs_free_dummy_fs_info(fs_info); |
dc11dd5d JB |
1062 | return ret; |
1063 | } |