Skip to content

Commit 9426ce7

Browse files
osandovkdave
authored andcommitted
Btrfs: fix extent buffer bitmap tests on big-endian systems
The in-memory bitmap code manipulates words and is therefore sensitive to endianness, while the extent buffer bitmap code addresses bytes and is byte-order agnostic. Because the byte addressing of the extent buffer bitmaps is equivalent to a little-endian in-memory bitmap, the extent buffer bitmap tests fail on big-endian systems. 34b3e6c ("Btrfs: self-tests: Fix extent buffer bitmap test fail on BE system") worked around another endianness bug in the tests but missed this one because ed9e4af ("Btrfs: self-tests: Execute page straddling test only when nodesize < PAGE_SIZE") disables this part of the test on ppc64. That change lost the original meaning of the test, however. We really want to test that an equivalent series of operations using the in-memory bitmap API and the extent buffer bitmap API produces equivalent results. To fix this, don't use memcmp_extent_buffer() or write_extent_buffer(); do everything bit-by-bit. Reported-by: Anatoly Pugachev <matorola@gmail.com> Tested-by: Anatoly Pugachev <matorola@gmail.com> Tested-by: Feifei Xu <xufeifei@linux.vnet.ibm.com> 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 6675df3 commit 9426ce7

1 file changed

Lines changed: 51 additions & 36 deletions

File tree

fs/btrfs/tests/extent-io-tests.c

Lines changed: 51 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -273,20 +273,37 @@ static int test_find_delalloc(u32 sectorsize)
273273
return ret;
274274
}
275275

276-
/**
277-
* test_bit_in_byte - Determine whether a bit is set in a byte
278-
* @nr: bit number to test
279-
* @addr: Address to start counting from
280-
*/
281-
static inline int test_bit_in_byte(int nr, const u8 *addr)
276+
static int check_eb_bitmap(unsigned long *bitmap, struct extent_buffer *eb,
277+
unsigned long len)
282278
{
283-
return 1UL & (addr[nr / BITS_PER_BYTE] >> (nr & (BITS_PER_BYTE - 1)));
279+
unsigned long i;
280+
281+
for (i = 0; i < len * BITS_PER_BYTE; i++) {
282+
int bit, bit1;
283+
284+
bit = !!test_bit(i, bitmap);
285+
bit1 = !!extent_buffer_test_bit(eb, 0, i);
286+
if (bit1 != bit) {
287+
test_msg("Bits do not match\n");
288+
return -EINVAL;
289+
}
290+
291+
bit1 = !!extent_buffer_test_bit(eb, i / BITS_PER_BYTE,
292+
i % BITS_PER_BYTE);
293+
if (bit1 != bit) {
294+
test_msg("Offset bits do not match\n");
295+
return -EINVAL;
296+
}
297+
}
298+
return 0;
284299
}
285300

286301
static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb,
287302
unsigned long len)
288303
{
289-
unsigned long i, x;
304+
unsigned long i, j;
305+
u32 x;
306+
int ret;
290307

291308
memset(bitmap, 0, len);
292309
memset_extent_buffer(eb, 0, 0, len);
@@ -297,16 +314,18 @@ static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb,
297314

298315
bitmap_set(bitmap, 0, len * BITS_PER_BYTE);
299316
extent_buffer_bitmap_set(eb, 0, 0, len * BITS_PER_BYTE);
300-
if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) {
317+
ret = check_eb_bitmap(bitmap, eb, len);
318+
if (ret) {
301319
test_msg("Setting all bits failed\n");
302-
return -EINVAL;
320+
return ret;
303321
}
304322

305323
bitmap_clear(bitmap, 0, len * BITS_PER_BYTE);
306324
extent_buffer_bitmap_clear(eb, 0, 0, len * BITS_PER_BYTE);
307-
if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) {
325+
ret = check_eb_bitmap(bitmap, eb, len);
326+
if (ret) {
308327
test_msg("Clearing all bits failed\n");
309-
return -EINVAL;
328+
return ret;
310329
}
311330

312331
/* Straddling pages test */
@@ -316,9 +335,10 @@ static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb,
316335
sizeof(long) * BITS_PER_BYTE);
317336
extent_buffer_bitmap_set(eb, PAGE_SIZE - sizeof(long) / 2, 0,
318337
sizeof(long) * BITS_PER_BYTE);
319-
if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) {
338+
ret = check_eb_bitmap(bitmap, eb, len);
339+
if (ret) {
320340
test_msg("Setting straddling pages failed\n");
321-
return -EINVAL;
341+
return ret;
322342
}
323343

324344
bitmap_set(bitmap, 0, len * BITS_PER_BYTE);
@@ -328,9 +348,10 @@ static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb,
328348
extent_buffer_bitmap_set(eb, 0, 0, len * BITS_PER_BYTE);
329349
extent_buffer_bitmap_clear(eb, PAGE_SIZE - sizeof(long) / 2, 0,
330350
sizeof(long) * BITS_PER_BYTE);
331-
if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) {
351+
ret = check_eb_bitmap(bitmap, eb, len);
352+
if (ret) {
332353
test_msg("Clearing straddling pages failed\n");
333-
return -EINVAL;
354+
return ret;
334355
}
335356
}
336357

@@ -339,28 +360,22 @@ static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb,
339360
* something repetitive that could miss some hypothetical off-by-n bug.
340361
*/
341362
x = 0;
342-
for (i = 0; i < len / sizeof(long); i++) {
343-
x = (0x19660dULL * (u64)x + 0x3c6ef35fULL) & 0xffffffffUL;
344-
bitmap[i] = x;
345-
}
346-
write_extent_buffer(eb, bitmap, 0, len);
347-
348-
for (i = 0; i < len * BITS_PER_BYTE; i++) {
349-
int bit, bit1;
350-
351-
bit = !!test_bit_in_byte(i, (u8 *)bitmap);
352-
bit1 = !!extent_buffer_test_bit(eb, 0, i);
353-
if (bit1 != bit) {
354-
test_msg("Testing bit pattern failed\n");
355-
return -EINVAL;
363+
bitmap_clear(bitmap, 0, len * BITS_PER_BYTE);
364+
extent_buffer_bitmap_clear(eb, 0, 0, len * BITS_PER_BYTE);
365+
for (i = 0; i < len * BITS_PER_BYTE / 32; i++) {
366+
x = (0x19660dULL * (u64)x + 0x3c6ef35fULL) & 0xffffffffU;
367+
for (j = 0; j < 32; j++) {
368+
if (x & (1U << j)) {
369+
bitmap_set(bitmap, i * 32 + j, 1);
370+
extent_buffer_bitmap_set(eb, 0, i * 32 + j, 1);
371+
}
356372
}
373+
}
357374

358-
bit1 = !!extent_buffer_test_bit(eb, i / BITS_PER_BYTE,
359-
i % BITS_PER_BYTE);
360-
if (bit1 != bit) {
361-
test_msg("Testing bit pattern with offset failed\n");
362-
return -EINVAL;
363-
}
375+
ret = check_eb_bitmap(bitmap, eb, len);
376+
if (ret) {
377+
test_msg("Random bit pattern failed\n");
378+
return ret;
364379
}
365380

366381
return 0;

0 commit comments

Comments
 (0)