bcache-tools: define separated super block for in-memory and on-disk format

This patch syncrhonizes the super block definition from bcache kernel
code, now the original super block structure is changed into two,
- struct cache_sb_disk
  This is for on-disk bcache super block format, which is exactly same
  as original struct cache_sb.
- struct cache_sb
  This is only for in-memory super block, it is no longer exactly
  mapping to the members and offsets to the cache_sb_disk.

Most part of the patch is to make source code to be consistent to the
data structures change.

Signed-off-by: Coly Li <colyli@suse.de>
diff --git a/Makefile b/Makefile
index 2c326cf..b4546a1 100644
--- a/Makefile
+++ b/Makefile
@@ -31,7 +31,7 @@
 
 bcache-super-show: LDLIBS += `pkg-config --libs uuid`
 bcache-super-show: CFLAGS += -std=gnu99
-bcache-super-show: crc64.o
+bcache-super-show: crc64.o lib.o
 
 bcache-register: bcache-register.o
 
diff --git a/bcache-super-show.c b/bcache-super-show.c
index 26cc40e..883410f 100644
--- a/bcache-super-show.c
+++ b/bcache-super-show.c
@@ -25,7 +25,8 @@
 #include <uuid/uuid.h>
 
 #include "bcache.h"
-
+#include "lib.h"
+#include "bitwise.h"
 
 static void usage()
 {
@@ -61,6 +62,7 @@
 	bool force_csum = false;
 	int o;
 	extern char *optarg;
+	struct cache_sb_disk sb_disk;
 	struct cache_sb sb;
 	char uuid[40];
 	uint64_t expected_csum;
@@ -90,11 +92,13 @@
 		exit(2);
 	}
 
-	if (pread(fd, &sb, sizeof(sb), SB_START) != sizeof(sb)) {
+	if (pread(fd, &sb_disk, sizeof(sb_disk), SB_START) != sizeof(sb_disk)) {
 		fprintf(stderr, "Couldn't read\n");
 		exit(2);
 	}
 
+	to_cache_sb(&sb, &sb_disk);
+
 	printf("sb.magic\t\t");
 	if (!memcmp(sb.magic, bcache_magic, 16)) {
 		printf("ok\n");
@@ -104,7 +108,7 @@
 		exit(2);
 	}
 
-	printf("sb.first_sector\t\t%" PRIu64, sb.offset);
+	printf("sb.first_sector\t\t%llu", sb.offset);
 	if (sb.offset == SB_SECTOR) {
 		printf(" [match]\n");
 	} else {
@@ -113,9 +117,9 @@
 		exit(2);
 	}
 
-	printf("sb.csum\t\t\t%" PRIX64, sb.csum);
-	expected_csum = csum_set(&sb);
-	if (sb.csum == expected_csum) {
+	printf("sb.csum\t\t\t%llx", le64_to_cpu(sb_disk.csum));
+	expected_csum = csum_set(&sb_disk);
+	if (le64_to_cpu(sb_disk.csum) == expected_csum) {
 		printf(" [match]\n");
 	} else {
 		printf(" [expected %" PRIX64 "]\n", expected_csum);
@@ -125,7 +129,7 @@
 		}
 	}
 
-	printf("sb.version\t\t%" PRIu64, sb.version);
+	printf("sb.version\t\t%llu", sb.version);
 	switch (sb.version) {
 		// These are handled the same by the kernel
 		case BCACHE_SB_VERSION_CDEV:
@@ -168,8 +172,8 @@
 	if (!SB_IS_BDEV(&sb)) {
 		// total_sectors includes the superblock;
 		printf("dev.cache.first_sector\t%u\n"
-		       "dev.cache.cache_sectors\t%ju\n"
-		       "dev.cache.total_sectors\t%ju\n"
+		       "dev.cache.cache_sectors\t%llu\n"
+		       "dev.cache.total_sectors\t%llu\n"
 		       "dev.cache.ordered\t%s\n"
 		       "dev.cache.discard\t%s\n"
 		       "dev.cache.pos\t\t%u\n"
diff --git a/bcache.h b/bcache.h
index 82fe580..250da9d 100644
--- a/bcache.h
+++ b/bcache.h
@@ -94,38 +94,41 @@
 	__le64			d[SB_JOURNAL_BUCKETS];	/* journal buckets */
 };
 
+/*
+ * This is for in-memory bcache super block.
+ * NOTE: cache_sb is NOT exactly mapping to cache_sb_disk, the member
+ *       size, ordering and even whole struct size may be different
+ *       from cache_sb_disk.
+ */
 struct cache_sb {
-	uint64_t		csum;
-	uint64_t		offset;	/* sector where this sb was written */
-	uint64_t		version;
+	__u64			offset; /* sector where this sb was written */
+	__u64			version;
 
-	uint8_t			magic[16];
+	__u8			magic[16];
 
-	uint8_t			uuid[16];
+	__u8			uuid[16];
 	union {
-		uint8_t		set_uuid[16];
-		uint64_t	set_magic;
+		__u8		set_uuid[16];
+		__u64		set_magic;
 	};
-	uint8_t			label[SB_LABEL_SIZE];
+	__u8			label[SB_LABEL_SIZE];
 
-	uint64_t		flags;
-	uint64_t		seq;
-	uint64_t		pad[8];
+	__u64			flags;
+	__u64			seq;
 
 	union {
 	struct {
 		/* Cache devices */
-		uint64_t	nbuckets;	/* device size */
+		__u64		nbuckets;	/* device size */
 
-		uint16_t	block_size;	/* sectors */
-		uint16_t	bucket_size;	/* sectors */
-
-		uint16_t	nr_in_set;
-		uint16_t	nr_this_dev;
+		__u16		block_size;	/* sectors */
+		__u16		nr_in_set;
+		__u16		nr_this_dev;
+		__u32		bucket_size;	/* sectors */
 	};
 	struct {
 		/* Backing devices */
-		uint64_t	data_offset;
+		__u64		data_offset;
 
 		/*
 		 * block_size from the cache device section is still used by
@@ -135,14 +138,14 @@
 	};
 	};
 
-	uint32_t		last_mount;	/* time_t */
+	__u32			last_mount;	/* time overflow in y2106 */
 
-	uint16_t		first_bucket;
+	__u16			first_bucket;
 	union {
-		uint16_t	njournal_buckets;
-		uint16_t	keys;
+		__u16		njournal_buckets;
+		__u16		keys;
 	};
-	uint64_t		d[SB_JOURNAL_BUCKETS];	/* journal buckets */
+	__u64			d[SB_JOURNAL_BUCKETS];  /* journal buckets */
 };
 
 static inline bool SB_IS_BDEV(const struct cache_sb *sb)
diff --git a/lib.c b/lib.c
index 542f115..9a2fa26 100644
--- a/lib.c
+++ b/lib.c
@@ -293,7 +293,6 @@
 	strcpy(base->name, devname);
 	base->magic = "ok";
 	base->first_sector = SB_SECTOR;
-	base->csum = sb.csum;
 	base->version = sb.version;
 
 	strncpy(base->label, (char *) sb.label, SB_LABEL_SIZE);
@@ -325,6 +324,7 @@
 
 int may_add_item(char *devname, struct list_head *head)
 {
+	struct cache_sb_disk sb_disk;
 	struct cache_sb sb;
 
 	if (strcmp(devname, ".") == 0 || strcmp(devname, "..") == 0)
@@ -336,10 +336,13 @@
 
 	if (fd == -1)
 		return 0;
-	if (pread(fd, &sb, sizeof(sb), SB_START) != sizeof(sb)) {
+	if (pread(fd, &sb_disk, sizeof(sb_disk), SB_START) != sizeof(sb_disk)) {
 		close(fd);
 		return 0;
 	}
+
+	to_cache_sb(&sb, &sb_disk);
+
 	if (memcmp(sb.magic, bcache_magic, 16)) {
 		close(fd);
 		return 0;
@@ -348,6 +351,8 @@
 	int ret;
 
 	tmp = (struct dev *) malloc(DEVLEN);
+
+	tmp->csum = le64_to_cpu(sb_disk.csum);
 	ret = detail_base(dev, sb, tmp);
 	if (ret != 0) {
 		fprintf(stderr, "Failed to get information for %s\n", dev);
@@ -399,6 +404,7 @@
 
 int detail_dev(char *devname, struct bdev *bd, struct cdev *cd, int *type)
 {
+	struct cache_sb_disk sb_disk;
 	struct cache_sb sb;
 	uint64_t expected_csum;
 	int fd = open(devname, O_RDONLY);
@@ -408,11 +414,13 @@
 		return 1;
 	}
 
-	if (pread(fd, &sb, sizeof(sb), SB_START) != sizeof(sb)) {
+	if (pread(fd, &sb_disk, sizeof(sb_disk), SB_START) != sizeof(sb_disk)) {
 		fprintf(stderr, "Couldn't read\n");
 		goto Fail;
 	}
 
+	to_cache_sb(&sb, &sb_disk);
+
 	if (memcmp(sb.magic, bcache_magic, 16)) {
 		fprintf(stderr,
 			"Bad magic,make sure this is an bcache device\n");
@@ -424,8 +432,8 @@
 		goto Fail;
 	}
 
-	expected_csum = csum_set(&sb);
-	if (!(sb.csum == expected_csum)) {
+	expected_csum = csum_set(&sb_disk);
+	if (le64_to_cpu(sb_disk.csum) != expected_csum) {
 		fprintf(stderr, "Csum is not match with expected one\n");
 		goto Fail;
 	}
diff --git a/make.c b/make.c
index cc76863..a239023 100644
--- a/make.c
+++ b/make.c
@@ -223,35 +223,6 @@
 	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,
@@ -261,9 +232,9 @@
 {
 	int fd;
 	char uuid_str[40], set_uuid_str[40], zeroes[SB_START] = {0};
+	struct cache_sb_disk sb_disk;
 	struct cache_sb sb;
 	blkid_probe pr;
-	int write_cdev_super = 1;
 
 	fd = open(dev, O_RDWR|O_EXCL);
 
@@ -320,13 +291,13 @@
 	if (force)
 		wipe_bcache = true;
 
-	if (pread(fd, &sb, sizeof(sb), SB_START) != sizeof(sb))
+	if (pread(fd, &sb_disk, sizeof(sb_disk), SB_START) != sizeof(sb_disk))
 		exit(EXIT_FAILURE);
 
-	if (!memcmp(sb.magic, bcache_magic, 16)) {
+	if (!memcmp(sb_disk.magic, bcache_magic, 16)) {
 		if (wipe_bcache) {
-			if (pwrite(fd, zeroes, sizeof(sb),
-				SB_START) != sizeof(sb)) {
+			if (pwrite(fd, zeroes, sizeof(sb_disk),
+				SB_START) != sizeof(sb_disk)) {
 				fprintf(stderr,
 					"Failed to erase super block for %s\n",
 					dev);
@@ -355,6 +326,7 @@
 		exit(EXIT_FAILURE);
 	}
 
+	memset(&sb_disk, 0, sizeof(struct cache_sb_disk));
 	memset(&sb, 0, sizeof(struct cache_sb));
 
 	sb.offset	= SB_SECTOR;
@@ -373,8 +345,6 @@
 	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);
 
@@ -415,7 +385,7 @@
 		sb.first_bucket		= (23 / sb.bucket_size) + 1;
 
 		if (sb.nbuckets < 1 << 7) {
-			fprintf(stderr, "Not enough buckets: %ju, need %u\n",
+			fprintf(stderr, "Not enough buckets: %llu, need %u\n",
 			       sb.nbuckets, 1 << 7);
 			exit(EXIT_FAILURE);
 		}
@@ -429,7 +399,7 @@
 		printf("UUID:			%s\n"
 		       "Set UUID:		%s\n"
 		       "version:		%u\n"
-		       "nbuckets:		%ju\n"
+		       "nbuckets:		%llu\n"
 		       "block_size_in_sectors:	%u\n"
 		       "bucket_size_in_sectors:	%u\n"
 		       "nr_in_set:		%u\n"
@@ -462,17 +432,17 @@
 	 * Swap native bytes order to little endian for writing
 	 * the super block out.
 	 */
-	swap_sb(&sb, write_cdev_super);
+	to_cache_sb_disk(&sb_disk, &sb);
 
 	/* write csum */
-	sb.csum = csum_set(&sb);
+	sb_disk.csum = cpu_to_le64(csum_set(&sb_disk));
 	/* Zero start of disk */
 	if (pwrite(fd, zeroes, SB_START, 0) != SB_START) {
 		perror("write error\n");
 		exit(EXIT_FAILURE);
 	}
 	/* Write superblock */
-	if (pwrite(fd, &sb, sizeof(sb), SB_START) != sizeof(sb)) {
+	if (pwrite(fd, &sb_disk, sizeof(sb_disk), SB_START) != sizeof(sb_disk)) {
 		perror("write error\n");
 		exit(EXIT_FAILURE);
 	}
diff --git a/probe-bcache.c b/probe-bcache.c
index c94c972..a640046 100644
--- a/probe-bcache.c
+++ b/probe-bcache.c
@@ -29,7 +29,7 @@
 	bool udev = false;
 	int i, o;
 	extern char *optarg;
-	struct cache_sb sb;
+	struct cache_sb_disk sb_disk;
 	char uuid[40];
 	blkid_probe pr;
 
@@ -66,13 +66,13 @@
 			continue;
 		}
 
-		if (pread(fd, &sb, sizeof(sb), SB_START) != sizeof(sb))
+		if (pread(fd, &sb_disk, sizeof(sb_disk), SB_START) != sizeof(sb_disk))
 			continue;
 
-		if (memcmp(sb.magic, bcache_magic, 16))
+		if (memcmp(sb_disk.magic, bcache_magic, 16))
 			continue;
 
-		uuid_unparse(sb.uuid, uuid);
+		uuid_unparse(sb_disk.uuid, uuid);
 
 		if (udev)
 			printf("ID_FS_UUID=%s\n"