Merge branch 'misc-cleanups-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git...
[cascardo/linux.git] / fs / btrfs / tests / extent-io-tests.c
index 6ec2bce..e29fa29 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <linux/pagemap.h>
 #include <linux/sched.h>
+#include <linux/slab.h>
 #include <linux/sizes.h>
 #include "btrfs-tests.h"
 #include "../extent_io.h"
@@ -77,6 +78,8 @@ static int test_find_delalloc(void)
        u64 found;
        int ret = -EINVAL;
 
+       test_msg("Running find delalloc tests\n");
+
        inode = btrfs_new_test_inode();
        if (!inode) {
                test_msg("Failed to allocate test inode\n");
@@ -269,8 +272,139 @@ out:
        return ret;
 }
 
+static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb,
+                            unsigned long len)
+{
+       unsigned long i, x;
+
+       memset(bitmap, 0, len);
+       memset_extent_buffer(eb, 0, 0, len);
+       if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) {
+               test_msg("Bitmap was not zeroed\n");
+               return -EINVAL;
+       }
+
+       bitmap_set(bitmap, 0, len * BITS_PER_BYTE);
+       extent_buffer_bitmap_set(eb, 0, 0, len * BITS_PER_BYTE);
+       if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) {
+               test_msg("Setting all bits failed\n");
+               return -EINVAL;
+       }
+
+       bitmap_clear(bitmap, 0, len * BITS_PER_BYTE);
+       extent_buffer_bitmap_clear(eb, 0, 0, len * BITS_PER_BYTE);
+       if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) {
+               test_msg("Clearing all bits failed\n");
+               return -EINVAL;
+       }
+
+       bitmap_set(bitmap, (PAGE_CACHE_SIZE - sizeof(long) / 2) * BITS_PER_BYTE,
+                  sizeof(long) * BITS_PER_BYTE);
+       extent_buffer_bitmap_set(eb, PAGE_CACHE_SIZE - sizeof(long) / 2, 0,
+                                sizeof(long) * BITS_PER_BYTE);
+       if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) {
+               test_msg("Setting straddling pages failed\n");
+               return -EINVAL;
+       }
+
+       bitmap_set(bitmap, 0, len * BITS_PER_BYTE);
+       bitmap_clear(bitmap,
+                    (PAGE_CACHE_SIZE - sizeof(long) / 2) * BITS_PER_BYTE,
+                    sizeof(long) * BITS_PER_BYTE);
+       extent_buffer_bitmap_set(eb, 0, 0, len * BITS_PER_BYTE);
+       extent_buffer_bitmap_clear(eb, PAGE_CACHE_SIZE - sizeof(long) / 2, 0,
+                                  sizeof(long) * BITS_PER_BYTE);
+       if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) {
+               test_msg("Clearing straddling pages failed\n");
+               return -EINVAL;
+       }
+
+       /*
+        * Generate a wonky pseudo-random bit pattern for the sake of not using
+        * something repetitive that could miss some hypothetical off-by-n bug.
+        */
+       x = 0;
+       for (i = 0; i < len / sizeof(long); i++) {
+               x = (0x19660dULL * (u64)x + 0x3c6ef35fULL) & 0xffffffffUL;
+               bitmap[i] = x;
+       }
+       write_extent_buffer(eb, bitmap, 0, len);
+
+       for (i = 0; i < len * BITS_PER_BYTE; i++) {
+               int bit, bit1;
+
+               bit = !!test_bit(i, bitmap);
+               bit1 = !!extent_buffer_test_bit(eb, 0, i);
+               if (bit1 != bit) {
+                       test_msg("Testing bit pattern failed\n");
+                       return -EINVAL;
+               }
+
+               bit1 = !!extent_buffer_test_bit(eb, i / BITS_PER_BYTE,
+                                               i % BITS_PER_BYTE);
+               if (bit1 != bit) {
+                       test_msg("Testing bit pattern with offset failed\n");
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
+static int test_eb_bitmaps(void)
+{
+       unsigned long len = PAGE_CACHE_SIZE * 4;
+       unsigned long *bitmap;
+       struct extent_buffer *eb;
+       int ret;
+
+       test_msg("Running extent buffer bitmap tests\n");
+
+       bitmap = kmalloc(len, GFP_NOFS);
+       if (!bitmap) {
+               test_msg("Couldn't allocate test bitmap\n");
+               return -ENOMEM;
+       }
+
+       eb = __alloc_dummy_extent_buffer(NULL, 0, len);
+       if (!eb) {
+               test_msg("Couldn't allocate test extent buffer\n");
+               kfree(bitmap);
+               return -ENOMEM;
+       }
+
+       ret = __test_eb_bitmaps(bitmap, eb, len);
+       if (ret)
+               goto out;
+
+       /* Do it over again with an extent buffer which isn't page-aligned. */
+       free_extent_buffer(eb);
+       eb = __alloc_dummy_extent_buffer(NULL, PAGE_CACHE_SIZE / 2, len);
+       if (!eb) {
+               test_msg("Couldn't allocate test extent buffer\n");
+               kfree(bitmap);
+               return -ENOMEM;
+       }
+
+       ret = __test_eb_bitmaps(bitmap, eb, len);
+out:
+       free_extent_buffer(eb);
+       kfree(bitmap);
+       return ret;
+}
+
 int btrfs_test_extent_io(void)
 {
-       test_msg("Running find delalloc tests\n");
-       return test_find_delalloc();
+       int ret;
+
+       test_msg("Running extent I/O tests\n");
+
+       ret = test_find_delalloc();
+       if (ret)
+               goto out;
+
+       ret = test_eb_bitmaps();
+out:
+       test_msg("Extent I/O tests finished\n");
+       return ret;
 }