Skip to content

Commit 781e3bc

Browse files
osandovkdave
authored andcommitted
Btrfs: expand free space tree sanity tests to catch endianness bug
The free space tree format conversion functions were broken on big-endian systems, but the sanity tests didn't catch it because all of the operations were aligned to multiple words. This was meant to catch any bugs in the extent buffer code's handling of high memory, but it ended up hiding the endianness bug. Expand the tests to do both sector-aligned and page-aligned operations. Tested-by: Chandan Rajendra <chandan@linux.vnet.ibm.com> Signed-off-by: Omar Sandoval <osandov@fb.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 9426ce7 commit 781e3bc

1 file changed

Lines changed: 96 additions & 68 deletions

File tree

fs/btrfs/tests/free-space-tree-tests.c

Lines changed: 96 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,6 @@ struct free_space_extent {
2727
u64 start, length;
2828
};
2929

30-
/*
31-
* The test cases align their operations to this in order to hit some of the
32-
* edge cases in the bitmap code.
33-
*/
34-
#define BITMAP_RANGE (BTRFS_FREE_SPACE_BITMAP_BITS * PAGE_SIZE)
35-
3630
static int __check_free_space_extents(struct btrfs_trans_handle *trans,
3731
struct btrfs_fs_info *fs_info,
3832
struct btrfs_block_group_cache *cache,
@@ -168,7 +162,8 @@ static int check_free_space_extents(struct btrfs_trans_handle *trans,
168162
static int test_empty_block_group(struct btrfs_trans_handle *trans,
169163
struct btrfs_fs_info *fs_info,
170164
struct btrfs_block_group_cache *cache,
171-
struct btrfs_path *path)
165+
struct btrfs_path *path,
166+
u32 alignment)
172167
{
173168
struct free_space_extent extents[] = {
174169
{cache->key.objectid, cache->key.offset},
@@ -181,7 +176,8 @@ static int test_empty_block_group(struct btrfs_trans_handle *trans,
181176
static int test_remove_all(struct btrfs_trans_handle *trans,
182177
struct btrfs_fs_info *fs_info,
183178
struct btrfs_block_group_cache *cache,
184-
struct btrfs_path *path)
179+
struct btrfs_path *path,
180+
u32 alignment)
185181
{
186182
struct free_space_extent extents[] = {};
187183
int ret;
@@ -201,16 +197,17 @@ static int test_remove_all(struct btrfs_trans_handle *trans,
201197
static int test_remove_beginning(struct btrfs_trans_handle *trans,
202198
struct btrfs_fs_info *fs_info,
203199
struct btrfs_block_group_cache *cache,
204-
struct btrfs_path *path)
200+
struct btrfs_path *path,
201+
u32 alignment)
205202
{
206203
struct free_space_extent extents[] = {
207-
{cache->key.objectid + BITMAP_RANGE,
208-
cache->key.offset - BITMAP_RANGE},
204+
{cache->key.objectid + alignment,
205+
cache->key.offset - alignment},
209206
};
210207
int ret;
211208

212209
ret = __remove_from_free_space_tree(trans, fs_info, cache, path,
213-
cache->key.objectid, BITMAP_RANGE);
210+
cache->key.objectid, alignment);
214211
if (ret) {
215212
test_msg("Could not remove free space\n");
216213
return ret;
@@ -224,17 +221,18 @@ static int test_remove_beginning(struct btrfs_trans_handle *trans,
224221
static int test_remove_end(struct btrfs_trans_handle *trans,
225222
struct btrfs_fs_info *fs_info,
226223
struct btrfs_block_group_cache *cache,
227-
struct btrfs_path *path)
224+
struct btrfs_path *path,
225+
u32 alignment)
228226
{
229227
struct free_space_extent extents[] = {
230-
{cache->key.objectid, cache->key.offset - BITMAP_RANGE},
228+
{cache->key.objectid, cache->key.offset - alignment},
231229
};
232230
int ret;
233231

234232
ret = __remove_from_free_space_tree(trans, fs_info, cache, path,
235233
cache->key.objectid +
236-
cache->key.offset - BITMAP_RANGE,
237-
BITMAP_RANGE);
234+
cache->key.offset - alignment,
235+
alignment);
238236
if (ret) {
239237
test_msg("Could not remove free space\n");
240238
return ret;
@@ -247,18 +245,19 @@ static int test_remove_end(struct btrfs_trans_handle *trans,
247245
static int test_remove_middle(struct btrfs_trans_handle *trans,
248246
struct btrfs_fs_info *fs_info,
249247
struct btrfs_block_group_cache *cache,
250-
struct btrfs_path *path)
248+
struct btrfs_path *path,
249+
u32 alignment)
251250
{
252251
struct free_space_extent extents[] = {
253-
{cache->key.objectid, BITMAP_RANGE},
254-
{cache->key.objectid + 2 * BITMAP_RANGE,
255-
cache->key.offset - 2 * BITMAP_RANGE},
252+
{cache->key.objectid, alignment},
253+
{cache->key.objectid + 2 * alignment,
254+
cache->key.offset - 2 * alignment},
256255
};
257256
int ret;
258257

259258
ret = __remove_from_free_space_tree(trans, fs_info, cache, path,
260-
cache->key.objectid + BITMAP_RANGE,
261-
BITMAP_RANGE);
259+
cache->key.objectid + alignment,
260+
alignment);
262261
if (ret) {
263262
test_msg("Could not remove free space\n");
264263
return ret;
@@ -271,10 +270,11 @@ static int test_remove_middle(struct btrfs_trans_handle *trans,
271270
static int test_merge_left(struct btrfs_trans_handle *trans,
272271
struct btrfs_fs_info *fs_info,
273272
struct btrfs_block_group_cache *cache,
274-
struct btrfs_path *path)
273+
struct btrfs_path *path,
274+
u32 alignment)
275275
{
276276
struct free_space_extent extents[] = {
277-
{cache->key.objectid, 2 * BITMAP_RANGE},
277+
{cache->key.objectid, 2 * alignment},
278278
};
279279
int ret;
280280

@@ -287,15 +287,15 @@ static int test_merge_left(struct btrfs_trans_handle *trans,
287287
}
288288

289289
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
290-
cache->key.objectid, BITMAP_RANGE);
290+
cache->key.objectid, alignment);
291291
if (ret) {
292292
test_msg("Could not add free space\n");
293293
return ret;
294294
}
295295

296296
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
297-
cache->key.objectid + BITMAP_RANGE,
298-
BITMAP_RANGE);
297+
cache->key.objectid + alignment,
298+
alignment);
299299
if (ret) {
300300
test_msg("Could not add free space\n");
301301
return ret;
@@ -308,10 +308,11 @@ static int test_merge_left(struct btrfs_trans_handle *trans,
308308
static int test_merge_right(struct btrfs_trans_handle *trans,
309309
struct btrfs_fs_info *fs_info,
310310
struct btrfs_block_group_cache *cache,
311-
struct btrfs_path *path)
311+
struct btrfs_path *path,
312+
u32 alignment)
312313
{
313314
struct free_space_extent extents[] = {
314-
{cache->key.objectid + BITMAP_RANGE, 2 * BITMAP_RANGE},
315+
{cache->key.objectid + alignment, 2 * alignment},
315316
};
316317
int ret;
317318

@@ -324,16 +325,16 @@ static int test_merge_right(struct btrfs_trans_handle *trans,
324325
}
325326

326327
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
327-
cache->key.objectid + 2 * BITMAP_RANGE,
328-
BITMAP_RANGE);
328+
cache->key.objectid + 2 * alignment,
329+
alignment);
329330
if (ret) {
330331
test_msg("Could not add free space\n");
331332
return ret;
332333
}
333334

334335
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
335-
cache->key.objectid + BITMAP_RANGE,
336-
BITMAP_RANGE);
336+
cache->key.objectid + alignment,
337+
alignment);
337338
if (ret) {
338339
test_msg("Could not add free space\n");
339340
return ret;
@@ -346,10 +347,11 @@ static int test_merge_right(struct btrfs_trans_handle *trans,
346347
static int test_merge_both(struct btrfs_trans_handle *trans,
347348
struct btrfs_fs_info *fs_info,
348349
struct btrfs_block_group_cache *cache,
349-
struct btrfs_path *path)
350+
struct btrfs_path *path,
351+
u32 alignment)
350352
{
351353
struct free_space_extent extents[] = {
352-
{cache->key.objectid, 3 * BITMAP_RANGE},
354+
{cache->key.objectid, 3 * alignment},
353355
};
354356
int ret;
355357

@@ -362,23 +364,23 @@ static int test_merge_both(struct btrfs_trans_handle *trans,
362364
}
363365

364366
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
365-
cache->key.objectid, BITMAP_RANGE);
367+
cache->key.objectid, alignment);
366368
if (ret) {
367369
test_msg("Could not add free space\n");
368370
return ret;
369371
}
370372

371373
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
372-
cache->key.objectid + 2 * BITMAP_RANGE,
373-
BITMAP_RANGE);
374+
cache->key.objectid + 2 * alignment,
375+
alignment);
374376
if (ret) {
375377
test_msg("Could not add free space\n");
376378
return ret;
377379
}
378380

379381
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
380-
cache->key.objectid + BITMAP_RANGE,
381-
BITMAP_RANGE);
382+
cache->key.objectid + alignment,
383+
alignment);
382384
if (ret) {
383385
test_msg("Could not add free space\n");
384386
return ret;
@@ -391,12 +393,13 @@ static int test_merge_both(struct btrfs_trans_handle *trans,
391393
static int test_merge_none(struct btrfs_trans_handle *trans,
392394
struct btrfs_fs_info *fs_info,
393395
struct btrfs_block_group_cache *cache,
394-
struct btrfs_path *path)
396+
struct btrfs_path *path,
397+
u32 alignment)
395398
{
396399
struct free_space_extent extents[] = {
397-
{cache->key.objectid, BITMAP_RANGE},
398-
{cache->key.objectid + 2 * BITMAP_RANGE, BITMAP_RANGE},
399-
{cache->key.objectid + 4 * BITMAP_RANGE, BITMAP_RANGE},
400+
{cache->key.objectid, alignment},
401+
{cache->key.objectid + 2 * alignment, alignment},
402+
{cache->key.objectid + 4 * alignment, alignment},
400403
};
401404
int ret;
402405

@@ -409,23 +412,23 @@ static int test_merge_none(struct btrfs_trans_handle *trans,
409412
}
410413

411414
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
412-
cache->key.objectid, BITMAP_RANGE);
415+
cache->key.objectid, alignment);
413416
if (ret) {
414417
test_msg("Could not add free space\n");
415418
return ret;
416419
}
417420

418421
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
419-
cache->key.objectid + 4 * BITMAP_RANGE,
420-
BITMAP_RANGE);
422+
cache->key.objectid + 4 * alignment,
423+
alignment);
421424
if (ret) {
422425
test_msg("Could not add free space\n");
423426
return ret;
424427
}
425428

426429
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
427-
cache->key.objectid + 2 * BITMAP_RANGE,
428-
BITMAP_RANGE);
430+
cache->key.objectid + 2 * alignment,
431+
alignment);
429432
if (ret) {
430433
test_msg("Could not add free space\n");
431434
return ret;
@@ -438,10 +441,11 @@ static int test_merge_none(struct btrfs_trans_handle *trans,
438441
typedef int (*test_func_t)(struct btrfs_trans_handle *,
439442
struct btrfs_fs_info *,
440443
struct btrfs_block_group_cache *,
441-
struct btrfs_path *);
444+
struct btrfs_path *,
445+
u32 alignment);
442446

443-
static int run_test(test_func_t test_func, int bitmaps,
444-
u32 sectorsize, u32 nodesize)
447+
static int run_test(test_func_t test_func, int bitmaps, u32 sectorsize,
448+
u32 nodesize, u32 alignment)
445449
{
446450
struct btrfs_fs_info *fs_info;
447451
struct btrfs_root *root = NULL;
@@ -480,7 +484,7 @@ static int run_test(test_func_t test_func, int bitmaps,
480484
btrfs_set_header_nritems(root->node, 0);
481485
root->alloc_bytenr += 2 * nodesize;
482486

483-
cache = btrfs_alloc_dummy_block_group(8 * BITMAP_RANGE, sectorsize);
487+
cache = btrfs_alloc_dummy_block_group(8 * alignment, sectorsize);
484488
if (!cache) {
485489
test_msg("Couldn't allocate dummy block group cache\n");
486490
ret = -ENOMEM;
@@ -514,7 +518,7 @@ static int run_test(test_func_t test_func, int bitmaps,
514518
}
515519
}
516520

517-
ret = test_func(&trans, root->fs_info, cache, path);
521+
ret = test_func(&trans, root->fs_info, cache, path, alignment);
518522
if (ret)
519523
goto out;
520524

@@ -539,15 +543,27 @@ static int run_test(test_func_t test_func, int bitmaps,
539543
return ret;
540544
}
541545

542-
static int run_test_both_formats(test_func_t test_func,
543-
u32 sectorsize, u32 nodesize)
546+
static int run_test_both_formats(test_func_t test_func, u32 sectorsize,
547+
u32 nodesize, u32 alignment)
544548
{
549+
int test_ret = 0;
545550
int ret;
546551

547-
ret = run_test(test_func, 0, sectorsize, nodesize);
548-
if (ret)
549-
return ret;
550-
return run_test(test_func, 1, sectorsize, nodesize);
552+
ret = run_test(test_func, 0, sectorsize, nodesize, alignment);
553+
if (ret) {
554+
test_msg("%pf failed with extents, sectorsize=%u, nodesize=%u, alignment=%u\n",
555+
test_func, sectorsize, nodesize, alignment);
556+
test_ret = ret;
557+
}
558+
559+
ret = run_test(test_func, 1, sectorsize, nodesize, alignment);
560+
if (ret) {
561+
test_msg("%pf failed with bitmaps, sectorsize=%u, nodesize=%u, alignment=%u\n",
562+
test_func, sectorsize, nodesize, alignment);
563+
test_ret = ret;
564+
}
565+
566+
return test_ret;
551567
}
552568

553569
int btrfs_test_free_space_tree(u32 sectorsize, u32 nodesize)
@@ -563,18 +579,30 @@ int btrfs_test_free_space_tree(u32 sectorsize, u32 nodesize)
563579
test_merge_both,
564580
test_merge_none,
565581
};
582+
u32 bitmap_alignment;
583+
int test_ret = 0;
566584
int i;
567585

586+
/*
587+
* Align some operations to a page to flush out bugs in the extent
588+
* buffer bitmap handling of highmem.
589+
*/
590+
bitmap_alignment = BTRFS_FREE_SPACE_BITMAP_BITS * PAGE_SIZE;
591+
568592
test_msg("Running free space tree tests\n");
569593
for (i = 0; i < ARRAY_SIZE(tests); i++) {
570-
int ret = run_test_both_formats(tests[i], sectorsize,
571-
nodesize);
572-
if (ret) {
573-
test_msg("%pf : sectorsize %u failed\n",
574-
tests[i], sectorsize);
575-
return ret;
576-
}
594+
int ret;
595+
596+
ret = run_test_both_formats(tests[i], sectorsize, nodesize,
597+
sectorsize);
598+
if (ret)
599+
test_ret = ret;
600+
601+
ret = run_test_both_formats(tests[i], sectorsize, nodesize,
602+
bitmap_alignment);
603+
if (ret)
604+
test_ret = ret;
577605
}
578606

579-
return 0;
607+
return test_ret;
580608
}

0 commit comments

Comments
 (0)