fs: btrfs: Fix cache alignment bugs
authorMarek Vasut <marex@denx.de>
Sat, 22 Sep 2018 02:13:35 +0000 (04:13 +0200)
committerTom Rini <trini@konsulko.com>
Sun, 30 Sep 2018 17:00:37 +0000 (13:00 -0400)
The btrfs implementation passes cache-unaligned buffers into the
block layer, which triggers cache alignment problems down in the
block device drivers. Align the buffers to prevent this.

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Marek Behun <marek.behun@nic.cz>
fs/btrfs/ctree.c
fs/btrfs/extent-io.c
fs/btrfs/super.c

index 4da36a9bc77a900d0e3075c41b935a6a69e9d4b6..18b47d92fe5f089b2fb3f44b4ddefb9c3fc429dc 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "btrfs.h"
 #include <malloc.h>
+#include <memalign.h>
 
 int btrfs_comp_keys(struct btrfs_key *a, struct btrfs_key *b)
 {
@@ -105,23 +106,24 @@ void btrfs_free_path(struct btrfs_path *p)
 
 static int read_tree_node(u64 physical, union btrfs_tree_node **buf)
 {
-       struct btrfs_header hdr;
-       unsigned long size, offset = sizeof(hdr);
+       ALLOC_CACHE_ALIGN_BUFFER(struct btrfs_header, hdr,
+                                sizeof(struct btrfs_header));
+       unsigned long size, offset = sizeof(*hdr);
        union btrfs_tree_node *res;
        u32 i;
 
-       if (!btrfs_devread(physical, sizeof(hdr), &hdr))
+       if (!btrfs_devread(physical, sizeof(*hdr), hdr))
                return -1;
 
-       btrfs_header_to_cpu(&hdr);
+       btrfs_header_to_cpu(hdr);
 
-       if (hdr.level)
+       if (hdr->level)
                size = sizeof(struct btrfs_node)
-                      + hdr.nritems * sizeof(struct btrfs_key_ptr);
+                      + hdr->nritems * sizeof(struct btrfs_key_ptr);
        else
                size = btrfs_info.sb.nodesize;
 
-       res = malloc(size);
+       res = malloc_cache_aligned(size);
        if (!res) {
                debug("%s: malloc failed\n", __func__);
                return -1;
@@ -133,12 +135,12 @@ static int read_tree_node(u64 physical, union btrfs_tree_node **buf)
                return -1;
        }
 
-       res->header = hdr;
-       if (hdr.level)
-               for (i = 0; i < hdr.nritems; ++i)
+       memcpy(&res->header, hdr, sizeof(*hdr));
+       if (hdr->level)
+               for (i = 0; i < hdr->nritems; ++i)
                        btrfs_key_ptr_to_cpu(&res->node.ptrs[i]);
        else
-               for (i = 0; i < hdr.nritems; ++i)
+               for (i = 0; i < hdr->nritems; ++i)
                        btrfs_item_to_cpu(&res->leaf.items[i]);
 
        *buf = res;
index 7263f41644e483eba9401a0f2f0700878a622a1b..66d0e1c7d65faf5a91da5ca985fdbdaace2825df 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "btrfs.h"
 #include <malloc.h>
+#include <memalign.h>
 
 u64 btrfs_read_extent_inline(struct btrfs_path *path,
                             struct btrfs_file_extent_item *extent, u64 offset,
@@ -89,7 +90,7 @@ u64 btrfs_read_extent_reg(struct btrfs_path *path,
                return size;
        }
 
-       cbuf = malloc(dlen > size ? clen + dlen : clen);
+       cbuf = malloc_cache_aligned(dlen > size ? clen + dlen : clen);
        if (!cbuf)
                return -1ULL;
 
index e680caa56a4d0a8063072ca60acf9780a325a558..7aaf8f9b0d860569921bc746ff5021a400590f43 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include "btrfs.h"
+#include <memalign.h>
 
 #define BTRFS_SUPER_FLAG_SUPP  (BTRFS_HEADER_FLAG_WRITTEN      \
                                 | BTRFS_HEADER_FLAG_RELOC      \
@@ -179,7 +180,7 @@ int btrfs_read_superblock(void)
                0x4000000000ull,
                0x4000000000000ull
        };
-       char raw_sb[BTRFS_SUPER_INFO_SIZE];
+       ALLOC_CACHE_ALIGN_BUFFER(char, raw_sb, BTRFS_SUPER_INFO_SIZE);
        struct btrfs_super_block *sb = (struct btrfs_super_block *) raw_sb;
        u64 dev_total_bytes;
        int i;