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
openSUSE Build Service is sponsored by