File 0010-make.c-add-swap_sb-to-supprt-big-endian-machine.patch of Package bcache-tools.14286
From 4c409e8837f60545eb49bb7c2265dd0ac1b3f4b1 Mon Sep 17 00:00:00 2001
From: Coly Li <colyli@suse.de>
Date: Thu, 12 Dec 2019 20:21:16 +0800
Subject: [PATCH 15/16] make.c: add swap_sb() to supprt big endian machine
Git-commit: 4c409e8837f60545eb49bb7c2265dd0ac1b3f4b1
Patch-mainline: bcache-tools-1.1
References: bsc#1139948
There is no cpu_to_le{64, 32, 16} routines in bcache-tools, but in
Linux kernel bcache driver, le{64, 32, 16} routines are used to read
bcache super block in. This is broken on big endian machine, because
the byte order swap in Linux kernel will swap the natively written
big-endian byte order swapped into little endian, then everything
is not at correct location and treated as broken by bcache driver.
This patch adds cpu_to_le(64, 32, 16) routines usage in make.c, which
are in swap_sb(). Now on big-endian machine, an extra bytes swapping
will convert the byte order to be in little endian. Then in Linux
kernel (of cause for big endian machine) the le{64, 32, 16}_to_cpu
routins will convert everything in correct byte order.
Signed-off-by: Coly Li <colyli@suse.de>
---
make.c | 40 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
diff --git a/make.c b/make.c
index 4244866..d46d925 100644
--- a/make.c
+++ b/make.c
@@ -34,6 +34,7 @@
#include "bcache.h"
#include "lib.h"
+#include "bitwise.h"
#define max(x, y) ({ \
typeof(x) _max1 = (x); \
@@ -221,6 +222,35 @@ err:
return -1;
}
+static void swap_sb(struct cache_sb *sb, int write_cdev_super)
+{
+ int i;
+
+ /* swap to little endian byte order to write */
+ sb->offset = cpu_to_le64(sb->offset);
+ sb->version = cpu_to_le64(sb->version);
+ sb->flags = cpu_to_le64(sb->flags);
+ sb->seq = cpu_to_le64(sb->seq);
+ sb->last_mount = cpu_to_le32(sb->last_mount);
+ sb->first_bucket = cpu_to_le16(sb->first_bucket);
+ sb->keys = cpu_to_le16(sb->keys);
+ sb->block_size = cpu_to_le16(sb->block_size);
+
+ for (i = 0; i < SB_JOURNAL_BUCKETS; i++)
+ sb->d[i] = cpu_to_le64(sb->d[i]);
+
+ if (write_cdev_super) {
+ /* Cache devices */
+ sb->nbuckets = cpu_to_le64(sb->nbuckets);
+ sb->bucket_size = cpu_to_le16(sb->bucket_size);
+ sb->nr_in_set = cpu_to_le16(sb->nr_in_set);
+ sb->nr_this_dev = cpu_to_le16(sb->nr_this_dev);
+ } else {
+ /* Backing devices */
+ sb->data_offset = cpu_to_le64(sb->data_offset);
+ }
+}
+
static void write_sb(char *dev, unsigned int block_size,
unsigned int bucket_size,
bool writeback, bool discard, bool wipe_bcache,
@@ -232,6 +262,7 @@ static void write_sb(char *dev, unsigned int block_size,
char uuid_str[40], set_uuid_str[40], zeroes[SB_START] = {0};
struct cache_sb sb;
blkid_probe pr;
+ int write_cdev_super = 1;
fd = open(dev, O_RDWR|O_EXCL);
@@ -341,6 +372,8 @@ static void write_sb(char *dev, unsigned int block_size,
uuid_unparse(sb.set_uuid, set_uuid_str);
if (SB_IS_BDEV(&sb)) {
+ write_cdev_super = 0;
+
SET_BDEV_CACHE_MODE(&sb, writeback ?
CACHE_MODE_WRITEBACK : CACHE_MODE_WRITETHROUGH);
@@ -410,6 +443,13 @@ static void write_sb(char *dev, unsigned int block_size,
for (i = 0; i < num; i++)
sb.label[i] = label[i];
sb.label[i] = '\0';
+
+ /*
+ * Swap native bytes order to little endian for writing
+ * the super block out.
+ */
+ swap_sb(&sb, write_cdev_super);
+
/* write csum */
sb.csum = csum_set(&sb);
/* Zero start of disk */
--
2.25.0