[U-Boot] [PATCH] fs: btrfs: Fix cache alignment bugs

Marek Vasut marex at denx.de
Sat Sep 22 02:13:35 UTC 2018


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 at denx.de>
Cc: Marek Behun <marek.behun at nic.cz>
---
 fs/btrfs/ctree.c     | 24 +++++++++++++-----------
 fs/btrfs/extent-io.c |  3 ++-
 fs/btrfs/super.c     |  3 ++-
 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;
-- 
2.18.0



More information about the U-Boot mailing list