summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Vasut <marex@denx.de>2018-09-22 04:13:35 +0200
committerTom Rini <trini@konsulko.com>2018-09-30 13:00:37 -0400
commitc9795396edd53ad29537037de8fd752662c676ad (patch)
treeb4489e56e5c686c6ed87a1e302b0a90f56e3d165
parent30b3241368aff899c56359f63214c164ed3fb3fb (diff)
fs: btrfs: Fix cache alignment bugs
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>
-rw-r--r--fs/btrfs/ctree.c24
-rw-r--r--fs/btrfs/extent-io.c3
-rw-r--r--fs/btrfs/super.c3
3 files changed, 17 insertions, 13 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 4da36a9bc7..18b47d92fe 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -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;
diff --git a/fs/btrfs/extent-io.c b/fs/btrfs/extent-io.c
index 7263f41644..66d0e1c7d6 100644
--- a/fs/btrfs/extent-io.c
+++ b/fs/btrfs/extent-io.c
@@ -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;
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index e680caa56a..7aaf8f9b0d 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -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;