Linux-bcache Archive on lore.kernel.org
 help / color / Atom feed
* [RFC PATCH 0/4] bcache-tools: changes for large bucket size
@ 2020-07-05 16:04 Coly Li
  2020-07-05 16:04 ` Coly Li
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Coly Li @ 2020-07-05 16:04 UTC (permalink / raw)
  To: linux-bcache; +Cc: linux-block, Coly Li

These are user space tools changes necessary for bcache large bucket
size. When setting bucket size with '-u' larger than 16MB for cache
device, BCACHE_SB_VERSION_CDEV_WITH_FEATURES will be set automatically.
Otherwise, the new added members in super block won't be touched.

Coly Li
---
Coly Li (4):
  bcache-tools: comments offset for members of struct cache_sb
  struct_offset: print offset of each member of the on-disk data
    structure
  bcache-tools: The new super block version
    BCACHE_SB_VERSION_BDEV_WITH_FEATURES
  bcache-tools: add large_bucket incompat feature

 Makefile        |   6 +-
 bcache.h        | 153 ++++++++++++++++++++++++++++++++++++++----------
 features.c      |  24 ++++++++
 lib.c           |  24 ++++++++
 lib.h           |   2 +
 make.c          |  36 ++++++++----
 struct_offset.c |  63 ++++++++++++++++++++
 7 files changed, 265 insertions(+), 43 deletions(-)
 create mode 100644 features.c
 create mode 100644 struct_offset.c

-- 
2.26.2

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [RFC PATCH 0/4] bcache-tools: changes for large bucket size
  2020-07-05 16:04 [RFC PATCH 0/4] bcache-tools: changes for large bucket size Coly Li
@ 2020-07-05 16:04 ` Coly Li
  2020-07-05 16:04 ` [RFC PATCH 1/4] bcache-tools: comments offset for members of struct cache_sb Coly Li
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Coly Li @ 2020-07-05 16:04 UTC (permalink / raw)
  To: linux-bcache; +Cc: linux-block, Coly Li

These are user space tools changes necessary for bcache large bucket
size. When setting bucket size with '-u' larger than 16MB for cache
device, BCACHE_SB_VERSION_CDEV_WITH_FEATURES will be set automatically.
Otherwise, the new added members in super block won't be touched.

Coly Li
---
Coly Li (4):
  bcache-tools: comments offset for members of struct cache_sb
  struct_offset: print offset of each member of the on-disk data
    structure
  bcache-tools: The new super block version
    BCACHE_SB_VERSION_BDEV_WITH_FEATURES
  bcache-tools: add large_bucket incompat feature

 Makefile        |   6 +-
 bcache.h        | 153 ++++++++++++++++++++++++++++++++++++++----------
 features.c      |  24 ++++++++
 lib.c           |  24 ++++++++
 lib.h           |   2 +
 make.c          |  36 ++++++++----
 struct_offset.c |  63 ++++++++++++++++++++
 7 files changed, 265 insertions(+), 43 deletions(-)
 create mode 100644 features.c
 create mode 100644 struct_offset.c

-- 
2.26.2


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [RFC PATCH 1/4] bcache-tools: comments offset for members of struct cache_sb
  2020-07-05 16:04 [RFC PATCH 0/4] bcache-tools: changes for large bucket size Coly Li
  2020-07-05 16:04 ` Coly Li
@ 2020-07-05 16:04 ` Coly Li
  2020-07-05 16:04 ` [RFC PATCH 2/4] struct_offset: print offset of each member of the on-disk data structure Coly Li
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Coly Li @ 2020-07-05 16:04 UTC (permalink / raw)
  To: linux-bcache; +Cc: linux-block, Coly Li

This patch adds code comments to mark the offset of each member from
struct cache_sb. It is helpful for understand the super block on disk.

Signed-off-by: Coly Li <colyli@suse.de>
---
 bcache.h | 64 ++++++++++++++++++++++++++++++--------------------------
 1 file changed, 34 insertions(+), 30 deletions(-)

diff --git a/bcache.h b/bcache.h
index c83f838..3fcf187 100644
--- a/bcache.h
+++ b/bcache.h
@@ -41,54 +41,58 @@ static const char bcache_magic[] = {
 #define SB_START		(SB_SECTOR * 512)
 
 struct cache_sb {
-	uint64_t		csum;
-	uint64_t		offset;	/* sector where this sb was written */
-	uint64_t		version;
+/*000*/	uint64_t		csum;
+	/* sector where this sb was written */
+/*008*/	uint64_t		offset;
+/*010*/	uint64_t		version;
 
-	uint8_t			magic[16];
+/*018*/	uint8_t			magic[16];
 
-	uint8_t			uuid[16];
+/*028*/	uint8_t			uuid[16];
 	union {
-		uint8_t		set_uuid[16];
-		uint64_t	set_magic;
+/*038*/		uint8_t		set_uuid[16];
+/*038*/		uint64_t	set_magic;
 	};
-	uint8_t			label[SB_LABEL_SIZE];
+/*048*/	uint8_t			label[SB_LABEL_SIZE];
 
-	uint64_t		flags;
-	uint64_t		seq;
-	uint64_t		pad[8];
+/*068*/	uint64_t		flags;
+/*070*/	uint64_t		seq;
+/*078*/	uint64_t		pad[8];
 
 	union {
 	struct {
-		/* Cache devices */
-		uint64_t	nbuckets;	/* device size */
+			/* Cache devices */
+/*0b8*/		uint64_t	nbuckets;	/* device size */
 
-		uint16_t	block_size;	/* sectors */
-		uint16_t	bucket_size;	/* sectors */
+/*0c0*/		uint16_t	block_size;	/* sectors */
+/*0c2*/		uint16_t	bucket_size;	/* sectors */
 
-		uint16_t	nr_in_set;
-		uint16_t	nr_this_dev;
+/*0c4*/		uint16_t	nr_in_set;
+/*0c6*/		uint16_t	nr_this_dev;
 	};
 	struct {
-		/* Backing devices */
-		uint64_t	data_offset;
-
-		/*
-		 * block_size from the cache device section is still used by
-		 * backing devices, so don't add anything here until we fix
-		 * things to not need it for backing devices anymore
-		 */
+			/* Backing devices */
+/*0b8*/		uint64_t	data_offset;
+
+			/*
+			 * block_size from the cache device section is still
+			 * used by backing devices, so don't add anything here
+			 * until we fix things to not need it for backing
+			 * devices anymore
+			 */
 	};
 	};
 
-	uint32_t		last_mount;	/* time_t */
+/*0c8*/	uint32_t		last_mount;	/* time_t */
 
-	uint16_t		first_bucket;
+/*0cc*/	uint16_t		first_bucket;
 	union {
-		uint16_t	njournal_buckets;
-		uint16_t	keys;
+/*0ce*/		uint16_t	njournal_buckets;
+/*0ce*/		uint16_t	keys;
 	};
-	uint64_t		d[SB_JOURNAL_BUCKETS];	/* journal buckets */
+	/* journal buckets */
+/*0d0*/	uint64_t		d[SB_JOURNAL_BUCKETS];
+/*8d0*/
 };
 
 static inline bool SB_IS_BDEV(const struct cache_sb *sb)
-- 
2.26.2

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [RFC PATCH 2/4] struct_offset: print offset of each member of the on-disk data structure
  2020-07-05 16:04 [RFC PATCH 0/4] bcache-tools: changes for large bucket size Coly Li
  2020-07-05 16:04 ` Coly Li
  2020-07-05 16:04 ` [RFC PATCH 1/4] bcache-tools: comments offset for members of struct cache_sb Coly Li
@ 2020-07-05 16:04 ` Coly Li
  2020-07-05 16:04 ` [RFC PATCH 3/4] bcache-tools: The new super block version BCACHE_SB_VERSION_BDEV_WITH_FEATURES Coly Li
  2020-07-05 16:04 ` [RFC PATCH 4/4] bcache-tools: add large_bucket incompat feature Coly Li
  4 siblings, 0 replies; 7+ messages in thread
From: Coly Li @ 2020-07-05 16:04 UTC (permalink / raw)
  To: linux-bcache; +Cc: linux-block, Coly Li

This is a helper small program to print out the offset in bytes of each
member of the on-disk data structure. Currently the member print lines
are coded manually, hope latter it can be more intelligent to avoid the
hard code.

Signed-off-by: Coly Li <colyli@suse.de>
---
 Makefile        |  4 +++-
 struct_offset.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+), 1 deletion(-)
 create mode 100644 struct_offset.c

diff --git a/Makefile b/Makefile
index 2c326cf..b352d21 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ DRACUTLIBDIR=/lib/dracut
 INSTALL=install
 CFLAGS+=-O2 -Wall -g
 
-all: make-bcache probe-bcache bcache-super-show bcache-register bcache
+all: make-bcache probe-bcache bcache-super-show bcache-register bcache struct_offset
 
 install: make-bcache probe-bcache bcache-super-show
 	$(INSTALL) -m0755 make-bcache bcache-super-show	bcache $(DESTDIR)${PREFIX}/sbin/
@@ -22,6 +22,8 @@ clean:
 
 bcache-test: LDLIBS += `pkg-config --libs openssl` -lm
 
+struct_offset: struct_offset.o
+
 make-bcache: LDLIBS += `pkg-config --libs uuid blkid smartcols`
 make-bcache: CFLAGS += `pkg-config --cflags uuid blkid smartcols`
 make-bcache: make.o crc64.o lib.o zoned.o
diff --git a/struct_offset.c b/struct_offset.c
new file mode 100644
index 0000000..6061259
--- /dev/null
+++ b/struct_offset.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Author: Coly Li <colyli@suse.de>
+ *
+ * Print out offset of each member of on-disk structure
+ */
+
+#include <stdio.h>
+#include <stddef.h>
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include "bcache.h"
+
+
+#define OFF_SB(m)	offsetof(struct cache_sb, m)
+
+void print_cache_sb()
+{
+	printf("	  struct cache_sb {:\n");
+	printf("/* %3.3lx */         uint64_t		csum;\n", OFF_SB(csum));
+	printf("/* %3.3lx */         uint64_t		offset;\n", OFF_SB(offset));
+	printf("/* %3.3lx */         uint64_t		version;\n", OFF_SB(version));
+	printf("/* %3.3lx */         uint8_t		magic[6];\n", OFF_SB(magic));
+	printf("/* %3.3lx */         uint8_t		uuid[16];\n", OFF_SB(uuid));
+	printf("                  union {;\n");
+	printf("/* %3.3lx */         	uint8_t		set_uuid;\n", OFF_SB(set_uuid));
+	printf("/* %3.3lx */         	uint64_t	set_magic;\n", OFF_SB(set_magic));
+	printf("		  };\n");
+	printf("/* %3.3lx */         uint8_t		label[%u];\n", OFF_SB(label),
+							SB_LABEL_SIZE);
+	printf("/* %3.3lx */         uint64_t		flags;\n", OFF_SB(flags));
+	printf("/* %3.3lx */         uint64_t		seq;\n", OFF_SB(seq));
+	printf("/* %3.3lx */         uint64_t		pad[8];\n", OFF_SB(pad));
+	printf("                  union {\n");
+	printf("                  struct {\n");
+	printf("/* %3.3lx */         	uint64_t	nbuckets;\n", OFF_SB(nbuckets));
+	printf("/* %3.3lx */         	uint16_t	block_size;\n", OFF_SB(block_size));
+	printf("/* %3.3lx */         	uint16_t	bucket_size;\n", OFF_SB(bucket_size));
+	printf("/* %3.3lx */         	uint16_t	nr_in_set;\n", OFF_SB(nr_in_set));
+	printf("/* %3.3lx */         	uint16_t	nr_this_dev;\n", OFF_SB(nr_this_dev));
+	printf("                  };\n");
+	printf("                  struct {\n");
+	printf("/* %3.3lx */          	uint64_t	data_offset;\n", OFF_SB(data_offset));
+	printf("                  };\n");
+	printf("                  };\n");
+	printf("/* %3.3lx */         uint32_t		last_mount;\n", OFF_SB(last_mount));
+	printf("/* %3.3lx */         uint16_t		first_bucket;\n", OFF_SB(first_bucket));
+	printf("                  union {\n");
+	printf("/* %3.3lx */         	uint16_t	njournal_buckets;\n", OFF_SB(njournal_buckets));
+	printf("/* %3.3lx */         	uint16_t	keys;\n", OFF_SB(keys));
+	printf("                  };\n");
+	printf("/* %3.3lx */         uint64_t		d[%u];\n", OFF_SB(d), SB_JOURNAL_BUCKETS);
+	printf("/* %3.3lx */ }\n", OFF_SB(d) + sizeof(uint64_t) * SB_JOURNAL_BUCKETS);
+}
+
+int main(int argc, char *argv[])
+{
+	print_cache_sb();
+	return 0;
+}
-- 
2.26.2

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [RFC PATCH 3/4] bcache-tools: The new super block version BCACHE_SB_VERSION_BDEV_WITH_FEATURES
  2020-07-05 16:04 [RFC PATCH 0/4] bcache-tools: changes for large bucket size Coly Li
                   ` (2 preceding siblings ...)
  2020-07-05 16:04 ` [RFC PATCH 2/4] struct_offset: print offset of each member of the on-disk data structure Coly Li
@ 2020-07-05 16:04 ` Coly Li
  2020-07-05 16:04 ` [RFC PATCH 4/4] bcache-tools: add large_bucket incompat feature Coly Li
  4 siblings, 0 replies; 7+ messages in thread
From: Coly Li @ 2020-07-05 16:04 UTC (permalink / raw)
  To: linux-bcache; +Cc: linux-block, Coly Li

The new super block version BCACHE_SB_VERSION_BDEV_WITH_FEATURES value
is 5, both cache device and backing device share this version number.

Devices have super block version equal to the new version will have
three new members,
/*078*/ uint64_t                feature_compat;
/*080*/ uint64_t                feature_incompat;
/*088*/ uint64_t                feature_ro_compat;

They are used for further new features which may introduce on-disk
format change, the very basic features handling code skeleton is also
initialized in this patch.

Signed-off-by: Coly Li <colyli@suse.de>
---
 Makefile        |  2 +-
 bcache.h        | 83 +++++++++++++++++++++++++++++++++++++++++++++++--
 features.c      | 22 +++++++++++++
 make.c          |  8 +++++
 struct_offset.c |  2 +-
 5 files changed, 113 insertions(+), 4 deletions(-)
 create mode 100644 features.c

diff --git a/Makefile b/Makefile
index b352d21..b5b41e4 100644
--- a/Makefile
+++ b/Makefile
@@ -40,4 +40,4 @@ bcache-register: bcache-register.o
 bcache: CFLAGS += `pkg-config --cflags blkid uuid smartcols`
 bcache: LDLIBS += `pkg-config --libs blkid uuid smartcols`
 bcache: CFLAGS += -std=gnu99
-bcache: crc64.o lib.o make.o zoned.o
+bcache: crc64.o lib.o make.o zoned.o features.o
diff --git a/bcache.h b/bcache.h
index 3fcf187..3695712 100644
--- a/bcache.h
+++ b/bcache.h
@@ -27,12 +27,16 @@ static const char bcache_magic[] = {
  * Version 2: Seed pointer into btree node checksum
  * Version 3: Cache device with new UUID format
  * Version 4: Backing device with data offset
+ * Version 5: Cache adn backing devices with compat/incompat/ro_compat
+ *            feature sets
  */
 #define BCACHE_SB_VERSION_CDEV			0
 #define BCACHE_SB_VERSION_BDEV			1
 #define BCACHE_SB_VERSION_CDEV_WITH_UUID	3
 #define BCACHE_SB_VERSION_BDEV_WITH_OFFSET	4
-#define BCACHE_SB_MAX_VERSION			4
+#define BCACHE_SB_VERSION_CDEV_WITH_FEATURES	5
+#define BCACHE_SB_VERSION_BDEV_WITH_FEATURES	6
+#define BCACHE_SB_MAX_VERSION			6
 
 #define SB_SECTOR		8
 #define SB_LABEL_SIZE		32
@@ -57,7 +61,12 @@ struct cache_sb {
 
 /*068*/	uint64_t		flags;
 /*070*/	uint64_t		seq;
-/*078*/	uint64_t		pad[8];
+
+/*078*/	uint64_t		feature_compat;
+/*080*/	uint64_t		feature_incompat;
+/*088*/	uint64_t		feature_ro_compat;
+
+/*090*/	uint64_t		pad[5];
 
 	union {
 	struct {
@@ -127,4 +136,74 @@ uint64_t crc64(const void *data, size_t len);
 #define csum_set(i)							\
 	crc64(((void *) (i)) + 8, ((void *) end(i)) - (((void *) (i)) + 8))
 
+#define BCH_FEATURE_COMPAT	0
+#define BCH_FEATURE_INCOMPAT	1
+#define BCH_FEATURE_RO_INCOMPAT	2
+#define BCH_FEATURE_TYPE_MASK	0x03
+
+#define BCH_FEATURE_COMPAT_SUUP		0
+#define BCH_FEATURE_INCOMPAT_SUUP	0
+#define BCH_FEATURE_RO_COMPAT_SUUP	0
+
+#define BCH_HAS_COMPAT_FEATURE(sb, mask) \
+		((sb)->feature_compat & (mask))
+#define BCH_HAS_RO_COMPAT_FEATURE(sb, mask) \
+		((sb)->feature_ro_compat & (mask))
+#define BCH_HAS_INCOMPAT_FEATURE(sb, mask) \
+		((sb)->feature_incompat & (mask))
+
+/* Feature set definition */
+
+
+#define BCH_FEATURE_COMPAT_FUNCS(name, flagname) \
+static inline int bch_has_feature_##name(struct cache_sb *sb) \
+{ \
+	return (((sb)->feature_compat & \
+		BCH##_FEATURE_COMPAT_##flagname) != 0); \
+} \
+static inline void bch_set_feature_##name(struct cache_sb *sb) \
+{ \
+	(sb)->feature_compat |= \
+		BCH##_FEATURE_COMPAT_##flagname; \
+} \
+static inline void bch_clear_feature_##name(struct cache_sb *sb) \
+{ \
+	(sb)->feature_compat &= \
+		~BCH##_FEATURE_COMPAT_##flagname; \
+}
+
+#define BCH_FEATURE_RO_COMPAT_FUNCS(name, flagname) \
+static inline int bch_has_feature_##name(struct cache_sb *sb) \
+{ \
+	return (((sb)->feature_ro_compat & \
+		BCH##_FEATURE_RO_COMPAT_##flagname) != 0); \
+} \
+static inline void bch_set_feature_##name(struct cache_sb *sb) \
+{ \
+	(sb)->feature_ro_compat |= \
+		BCH##_FEATURE_RO_COMPAT_##flagname; \
+} \
+static inline void bch_clear_feature_##name(struct cache_sb *sb) \
+{ \
+	(sb)->feature_ro_compat &= \
+		~BCH##_FEATURE_RO_COMPAT_##flagname; \
+}
+
+#define BCH_FEATURE_INCOMPAT_FUNCS(name, flagname) \
+static inline int bch_has_feature_##name(struct cache_sb *sb) \
+{ \
+	return (((sb)->feature_incompat & \
+		BCH##_FEATURE_INCOMPAT_##flagname) != 0); \
+} \
+static inline void bch_set_feature_##name(struct cache_sb *sb) \
+{ \
+	(sb)->feature_incompat |= \
+		BCH##_FEATURE_INCOMPAT_##flagname; \
+} \
+static inline void bch_clear_feature_##name(struct cache_sb *sb) \
+{ \
+	(sb)->feature_incompat &= \
+		~BCH##_FEATURE_INCOMPAT_##flagname; \
+}
+
 #endif
diff --git a/features.c b/features.c
new file mode 100644
index 0000000..013a5ca
--- /dev/null
+++ b/features.c
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Author: Coly Li <colyli@suse.de>
+ *
+ * Inspired by e2fsprogs features compat/incompat/ro_compat
+ * related code.
+ */
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "bcache.h"
+
+struct feature {
+	int		compat;
+	unsigned int	mask;
+	const char	*string;
+};
+
+static struct feature feature_list[] = {
+	{0, 0, 0 },
+};
diff --git a/make.c b/make.c
index cc76863..6d37532 100644
--- a/make.c
+++ b/make.c
@@ -250,6 +250,14 @@ static void swap_sb(struct cache_sb *sb, int write_cdev_super)
 		/* Backing devices */
 		sb->data_offset	= cpu_to_le64(sb->data_offset);
 	}
+
+	/* Convert feature set and version at last */
+	if (sb->version >= BCACHE_SB_VERSION_CDEV_WITH_FEATURES) {
+		sb->feature_compat = cpu_to_le64(sb->feature_compat);
+		sb->feature_incompat = cpu_to_le64(sb->feature_incompat);
+		sb->feature_ro_compat = cpu_to_le64(sb->feature_ro_compat);
+	}
+	sb->version		= cpu_to_le64(sb->version);
 }
 
 static void write_sb(char *dev, unsigned int block_size,
diff --git a/struct_offset.c b/struct_offset.c
index 6061259..54d4a34 100644
--- a/struct_offset.c
+++ b/struct_offset.c
@@ -52,7 +52,7 @@ void print_cache_sb()
 	printf("/* %3.3lx */         	uint16_t	keys;\n", OFF_SB(keys));
 	printf("                  };\n");
 	printf("/* %3.3lx */         uint64_t		d[%u];\n", OFF_SB(d), SB_JOURNAL_BUCKETS);
-	printf("/* %3.3lx */ }\n", OFF_SB(d) + sizeof(uint64_t) * SB_JOURNAL_BUCKETS);
+	printf("/* %3.3lx */ }\n", sizeof(struct cache_sb));
 }
 
 int main(int argc, char *argv[])
-- 
2.26.2

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [RFC PATCH 4/4] bcache-tools: add large_bucket incompat feature
  2020-07-05 16:04 [RFC PATCH 0/4] bcache-tools: changes for large bucket size Coly Li
                   ` (3 preceding siblings ...)
  2020-07-05 16:04 ` [RFC PATCH 3/4] bcache-tools: The new super block version BCACHE_SB_VERSION_BDEV_WITH_FEATURES Coly Li
@ 2020-07-05 16:04 ` Coly Li
  2020-07-05 16:04   ` Coly Li
  4 siblings, 1 reply; 7+ messages in thread
From: Coly Li @ 2020-07-05 16:04 UTC (permalink / raw)
  To: linux-bcache; +Cc: linux-block, Coly Li

This feature adds uint32_t bucket_size_hi into struct cache_sb, permit
bucket size to be 32bit width. Current maximum bucket size is 32MB,
extend it to 32bits will permit much large bucket size which is
desired by zoned SSD devices (a typical zone size is 256MB).

When setting a bucket size > 32MB, large_bucket feature will be set
automatically and the super block version will also be set to
BCACHE_SB_VERSION_CDEV_WITH_FEATURES.

Signed-off-by: Coly Li <colyli@suse.de>
---
 bcache.h        | 10 +++++++++-
 features.c      |  2 ++
 lib.c           | 24 ++++++++++++++++++++++++
 lib.h           |  2 ++
 make.c          | 28 ++++++++++++++++++----------
 struct_offset.c |  1 +
 6 files changed, 56 insertions(+), 11 deletions(-)

diff --git a/bcache.h b/bcache.h
index 3695712..6e1563b 100644
--- a/bcache.h
+++ b/bcache.h
@@ -101,7 +101,8 @@ struct cache_sb {
 	};
 	/* journal buckets */
 /*0d0*/	uint64_t		d[SB_JOURNAL_BUCKETS];
-/*8d0*/
+/*8d0*/	uint32_t		bucket_size_hi;
+/*8d4*/
 };
 
 static inline bool SB_IS_BDEV(const struct cache_sb *sb)
@@ -155,6 +156,11 @@ uint64_t crc64(const void *data, size_t len);
 /* Feature set definition */
 
 
+/* Feature set definition */
+
+/* Incompat feature set */
+#define BCH_FEATURE_INCOMPAT_LARGE_BUCKET	0x0001 /* 32bit bucket size */
+
 #define BCH_FEATURE_COMPAT_FUNCS(name, flagname) \
 static inline int bch_has_feature_##name(struct cache_sb *sb) \
 { \
@@ -206,4 +212,6 @@ static inline void bch_clear_feature_##name(struct cache_sb *sb) \
 		~BCH##_FEATURE_INCOMPAT_##flagname; \
 }
 
+BCH_FEATURE_INCOMPAT_FUNCS(large_bucket, LARGE_BUCKET);
+
 #endif
diff --git a/features.c b/features.c
index 013a5ca..9b6e93d 100644
--- a/features.c
+++ b/features.c
@@ -18,5 +18,7 @@ struct feature {
 };
 
 static struct feature feature_list[] = {
+	{BCH_FEATURE_COMPAT, BCH_FEATURE_INCOMPAT_LARGE_BUCKET,
+		"large_bucket"},
 	{0, 0, 0 },
 };
diff --git a/lib.c b/lib.c
index 9e69419..76e8b0d 100644
--- a/lib.c
+++ b/lib.c
@@ -4,6 +4,7 @@
 #include <stdbool.h>
 #include <blkid.h>
 #include <dirent.h>
+#include <limits.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <stdio.h>
@@ -681,3 +682,26 @@ int set_label(char *devname, char *label)
 	close(fd);
 	return 0;
 }
+
+void set_bucket_size(struct cache_sb *sb, unsigned int bucket_size)
+{
+	if (bucket_size > USHRT_MAX) {
+		sb->version = BCACHE_SB_VERSION_CDEV_WITH_FEATURES;
+		bch_set_feature_large_bucket(sb);
+		sb->bucket_size = (uint16_t)bucket_size;
+		sb->bucket_size_hi = (uint32_t)(bucket_size >> 16);
+	} else {
+		sb->bucket_size = bucket_size;
+	}
+}
+
+unsigned int get_bucket_size(struct cache_sb *sb)
+{
+	unsigned int bucket_size = sb->bucket_size;
+
+	if (sb->version >= BCACHE_SB_VERSION_CDEV_WITH_FEATURES &&
+	    bch_has_feature_large_bucket(sb))
+		bucket_size |= sb->bucket_size_hi << 16;
+
+	return bucket_size;
+}
diff --git a/lib.h b/lib.h
index d4537b0..a69e1b8 100644
--- a/lib.h
+++ b/lib.h
@@ -50,6 +50,8 @@ int detach_backdev(char *devname);
 int set_backdev_cachemode(char *devname, char *cachemode);
 int set_label(char *devname, char *label);
 int cset_to_devname(struct list_head *head, char *cset, char *devname);
+void set_bucket_size(struct cache_sb *sb, unsigned int bucket_size);
+unsigned int get_bucket_size(struct cache_sb *sb);
 
 
 #define DEVLEN sizeof(struct dev)
diff --git a/make.c b/make.c
index 6d37532..b788de1 100644
--- a/make.c
+++ b/make.c
@@ -83,7 +83,9 @@ uint64_t hatoi(const char *s)
 	return i;
 }
 
-unsigned int hatoi_validate(const char *s, const char *msg)
+unsigned int hatoi_validate(const char *s,
+			    const char *msg,
+			    unsigned long max)
 {
 	uint64_t v = hatoi(s);
 
@@ -94,7 +96,7 @@ unsigned int hatoi_validate(const char *s, const char *msg)
 
 	v /= 512;
 
-	if (v > USHRT_MAX) {
+	if (v > max) {
 		fprintf(stderr, "%s too large\n", msg);
 		exit(EXIT_FAILURE);
 	}
@@ -229,7 +231,6 @@ static void swap_sb(struct cache_sb *sb, int write_cdev_super)
 
 	/* 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);
@@ -244,6 +245,9 @@ static void swap_sb(struct cache_sb *sb, int write_cdev_super)
 		/* Cache devices */
 		sb->nbuckets	= cpu_to_le64(sb->nbuckets);
 		sb->bucket_size	= cpu_to_le16(sb->bucket_size);
+		if (sb->version >= BCACHE_SB_VERSION_CDEV_WITH_FEATURES &&
+		    bch_has_feature_large_bucket(sb))
+			sb->bucket_size_hi = cpu_to_le32(sb->bucket_size_hi);
 		sb->nr_in_set	= cpu_to_le16(sb->nr_in_set);
 		sb->nr_this_dev	= cpu_to_le16(sb->nr_this_dev);
 	} else {
@@ -374,7 +378,7 @@ static void write_sb(char *dev, unsigned int block_size,
 	uuid_generate(sb.uuid);
 	memcpy(sb.set_uuid, set_uuid, sizeof(sb.set_uuid));
 
-	sb.bucket_size	= bucket_size;
+	set_bucket_size(&sb, bucket_size);
 	sb.block_size	= block_size;
 
 	uuid_unparse(sb.uuid, uuid_str);
@@ -400,7 +404,8 @@ static void write_sb(char *dev, unsigned int block_size,
 		}
 
 		if (data_offset != BDEV_DATA_START_DEFAULT) {
-			sb.version = BCACHE_SB_VERSION_BDEV_WITH_OFFSET;
+			if (sb.version < BCACHE_SB_VERSION_BDEV_WITH_OFFSET)
+				sb.version = BCACHE_SB_VERSION_BDEV_WITH_OFFSET;
 			sb.data_offset = data_offset;
 		}
 
@@ -418,9 +423,10 @@ static void write_sb(char *dev, unsigned int block_size,
 		       data_offset);
 		putchar('\n');
 	} else {
-		sb.nbuckets		= getblocks(fd) / sb.bucket_size;
+		sb.nbuckets		= getblocks(fd) / get_bucket_size(&sb);
 		sb.nr_in_set		= 1;
-		sb.first_bucket		= (23 / sb.bucket_size) + 1;
+		/* 23 is (SB_SECTOR + SB_SIZE) - 1 sectors */
+		sb.first_bucket		= (23 / get_bucket_size(&sb)) + 1;
 
 		if (sb.nbuckets < 1 << 7) {
 			fprintf(stderr, "Not enough buckets: %ju, need %u\n",
@@ -447,7 +453,7 @@ static void write_sb(char *dev, unsigned int block_size,
 		       (unsigned int) sb.version,
 		       sb.nbuckets,
 		       sb.block_size,
-		       sb.bucket_size,
+		       get_bucket_size(&sb),
 		       sb.nr_in_set,
 		       sb.nr_this_dev,
 		       sb.first_bucket);
@@ -576,10 +582,12 @@ int make_bcache(int argc, char **argv)
 			bdev = 1;
 			break;
 		case 'b':
-			bucket_size = hatoi_validate(optarg, "bucket size");
+			bucket_size =
+				hatoi_validate(optarg, "bucket size", UINT_MAX);
 			break;
 		case 'w':
-			block_size = hatoi_validate(optarg, "block size");
+			block_size =
+				hatoi_validate(optarg, "block size", USHRT_MAX);
 			break;
 #if 0
 		case 'U':
diff --git a/struct_offset.c b/struct_offset.c
index 54d4a34..4ffacf7 100644
--- a/struct_offset.c
+++ b/struct_offset.c
@@ -52,6 +52,7 @@ void print_cache_sb()
 	printf("/* %3.3lx */         	uint16_t	keys;\n", OFF_SB(keys));
 	printf("                  };\n");
 	printf("/* %3.3lx */         uint64_t		d[%u];\n", OFF_SB(d), SB_JOURNAL_BUCKETS);
+	printf("/* %3.3lx */         uint32_t		bucket_size_hi;\n", OFF_SB(bucket_size_hi));
 	printf("/* %3.3lx */ }\n", sizeof(struct cache_sb));
 }
 
-- 
2.26.2

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [RFC PATCH 4/4] bcache-tools: add large_bucket incompat feature
  2020-07-05 16:04 ` [RFC PATCH 4/4] bcache-tools: add large_bucket incompat feature Coly Li
@ 2020-07-05 16:04   ` Coly Li
  0 siblings, 0 replies; 7+ messages in thread
From: Coly Li @ 2020-07-05 16:04 UTC (permalink / raw)
  To: linux-bcache; +Cc: linux-block, Coly Li

This feature adds uint32_t bucket_size_hi into struct cache_sb, permit
bucket size to be 32bit width. Current maximum bucket size is 32MB,
extend it to 32bits will permit much large bucket size which is
desired by zoned SSD devices (a typical zone size is 256MB).

When setting a bucket size > 32MB, large_bucket feature will be set
automatically and the super block version will also be set to
BCACHE_SB_VERSION_CDEV_WITH_FEATURES.

Signed-off-by: Coly Li <colyli@suse.de>
---
 bcache.h        | 10 +++++++++-
 features.c      |  2 ++
 lib.c           | 24 ++++++++++++++++++++++++
 lib.h           |  2 ++
 make.c          | 28 ++++++++++++++++++----------
 struct_offset.c |  1 +
 6 files changed, 56 insertions(+), 11 deletions(-)

diff --git a/bcache.h b/bcache.h
index 3695712..6e1563b 100644
--- a/bcache.h
+++ b/bcache.h
@@ -101,7 +101,8 @@ struct cache_sb {
 	};
 	/* journal buckets */
 /*0d0*/	uint64_t		d[SB_JOURNAL_BUCKETS];
-/*8d0*/
+/*8d0*/	uint32_t		bucket_size_hi;
+/*8d4*/
 };
 
 static inline bool SB_IS_BDEV(const struct cache_sb *sb)
@@ -155,6 +156,11 @@ uint64_t crc64(const void *data, size_t len);
 /* Feature set definition */
 
 
+/* Feature set definition */
+
+/* Incompat feature set */
+#define BCH_FEATURE_INCOMPAT_LARGE_BUCKET	0x0001 /* 32bit bucket size */
+
 #define BCH_FEATURE_COMPAT_FUNCS(name, flagname) \
 static inline int bch_has_feature_##name(struct cache_sb *sb) \
 { \
@@ -206,4 +212,6 @@ static inline void bch_clear_feature_##name(struct cache_sb *sb) \
 		~BCH##_FEATURE_INCOMPAT_##flagname; \
 }
 
+BCH_FEATURE_INCOMPAT_FUNCS(large_bucket, LARGE_BUCKET);
+
 #endif
diff --git a/features.c b/features.c
index 013a5ca..9b6e93d 100644
--- a/features.c
+++ b/features.c
@@ -18,5 +18,7 @@ struct feature {
 };
 
 static struct feature feature_list[] = {
+	{BCH_FEATURE_COMPAT, BCH_FEATURE_INCOMPAT_LARGE_BUCKET,
+		"large_bucket"},
 	{0, 0, 0 },
 };
diff --git a/lib.c b/lib.c
index 9e69419..76e8b0d 100644
--- a/lib.c
+++ b/lib.c
@@ -4,6 +4,7 @@
 #include <stdbool.h>
 #include <blkid.h>
 #include <dirent.h>
+#include <limits.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <stdio.h>
@@ -681,3 +682,26 @@ int set_label(char *devname, char *label)
 	close(fd);
 	return 0;
 }
+
+void set_bucket_size(struct cache_sb *sb, unsigned int bucket_size)
+{
+	if (bucket_size > USHRT_MAX) {
+		sb->version = BCACHE_SB_VERSION_CDEV_WITH_FEATURES;
+		bch_set_feature_large_bucket(sb);
+		sb->bucket_size = (uint16_t)bucket_size;
+		sb->bucket_size_hi = (uint32_t)(bucket_size >> 16);
+	} else {
+		sb->bucket_size = bucket_size;
+	}
+}
+
+unsigned int get_bucket_size(struct cache_sb *sb)
+{
+	unsigned int bucket_size = sb->bucket_size;
+
+	if (sb->version >= BCACHE_SB_VERSION_CDEV_WITH_FEATURES &&
+	    bch_has_feature_large_bucket(sb))
+		bucket_size |= sb->bucket_size_hi << 16;
+
+	return bucket_size;
+}
diff --git a/lib.h b/lib.h
index d4537b0..a69e1b8 100644
--- a/lib.h
+++ b/lib.h
@@ -50,6 +50,8 @@ int detach_backdev(char *devname);
 int set_backdev_cachemode(char *devname, char *cachemode);
 int set_label(char *devname, char *label);
 int cset_to_devname(struct list_head *head, char *cset, char *devname);
+void set_bucket_size(struct cache_sb *sb, unsigned int bucket_size);
+unsigned int get_bucket_size(struct cache_sb *sb);
 
 
 #define DEVLEN sizeof(struct dev)
diff --git a/make.c b/make.c
index 6d37532..b788de1 100644
--- a/make.c
+++ b/make.c
@@ -83,7 +83,9 @@ uint64_t hatoi(const char *s)
 	return i;
 }
 
-unsigned int hatoi_validate(const char *s, const char *msg)
+unsigned int hatoi_validate(const char *s,
+			    const char *msg,
+			    unsigned long max)
 {
 	uint64_t v = hatoi(s);
 
@@ -94,7 +96,7 @@ unsigned int hatoi_validate(const char *s, const char *msg)
 
 	v /= 512;
 
-	if (v > USHRT_MAX) {
+	if (v > max) {
 		fprintf(stderr, "%s too large\n", msg);
 		exit(EXIT_FAILURE);
 	}
@@ -229,7 +231,6 @@ static void swap_sb(struct cache_sb *sb, int write_cdev_super)
 
 	/* 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);
@@ -244,6 +245,9 @@ static void swap_sb(struct cache_sb *sb, int write_cdev_super)
 		/* Cache devices */
 		sb->nbuckets	= cpu_to_le64(sb->nbuckets);
 		sb->bucket_size	= cpu_to_le16(sb->bucket_size);
+		if (sb->version >= BCACHE_SB_VERSION_CDEV_WITH_FEATURES &&
+		    bch_has_feature_large_bucket(sb))
+			sb->bucket_size_hi = cpu_to_le32(sb->bucket_size_hi);
 		sb->nr_in_set	= cpu_to_le16(sb->nr_in_set);
 		sb->nr_this_dev	= cpu_to_le16(sb->nr_this_dev);
 	} else {
@@ -374,7 +378,7 @@ static void write_sb(char *dev, unsigned int block_size,
 	uuid_generate(sb.uuid);
 	memcpy(sb.set_uuid, set_uuid, sizeof(sb.set_uuid));
 
-	sb.bucket_size	= bucket_size;
+	set_bucket_size(&sb, bucket_size);
 	sb.block_size	= block_size;
 
 	uuid_unparse(sb.uuid, uuid_str);
@@ -400,7 +404,8 @@ static void write_sb(char *dev, unsigned int block_size,
 		}
 
 		if (data_offset != BDEV_DATA_START_DEFAULT) {
-			sb.version = BCACHE_SB_VERSION_BDEV_WITH_OFFSET;
+			if (sb.version < BCACHE_SB_VERSION_BDEV_WITH_OFFSET)
+				sb.version = BCACHE_SB_VERSION_BDEV_WITH_OFFSET;
 			sb.data_offset = data_offset;
 		}
 
@@ -418,9 +423,10 @@ static void write_sb(char *dev, unsigned int block_size,
 		       data_offset);
 		putchar('\n');
 	} else {
-		sb.nbuckets		= getblocks(fd) / sb.bucket_size;
+		sb.nbuckets		= getblocks(fd) / get_bucket_size(&sb);
 		sb.nr_in_set		= 1;
-		sb.first_bucket		= (23 / sb.bucket_size) + 1;
+		/* 23 is (SB_SECTOR + SB_SIZE) - 1 sectors */
+		sb.first_bucket		= (23 / get_bucket_size(&sb)) + 1;
 
 		if (sb.nbuckets < 1 << 7) {
 			fprintf(stderr, "Not enough buckets: %ju, need %u\n",
@@ -447,7 +453,7 @@ static void write_sb(char *dev, unsigned int block_size,
 		       (unsigned int) sb.version,
 		       sb.nbuckets,
 		       sb.block_size,
-		       sb.bucket_size,
+		       get_bucket_size(&sb),
 		       sb.nr_in_set,
 		       sb.nr_this_dev,
 		       sb.first_bucket);
@@ -576,10 +582,12 @@ int make_bcache(int argc, char **argv)
 			bdev = 1;
 			break;
 		case 'b':
-			bucket_size = hatoi_validate(optarg, "bucket size");
+			bucket_size =
+				hatoi_validate(optarg, "bucket size", UINT_MAX);
 			break;
 		case 'w':
-			block_size = hatoi_validate(optarg, "block size");
+			block_size =
+				hatoi_validate(optarg, "block size", USHRT_MAX);
 			break;
 #if 0
 		case 'U':
diff --git a/struct_offset.c b/struct_offset.c
index 54d4a34..4ffacf7 100644
--- a/struct_offset.c
+++ b/struct_offset.c
@@ -52,6 +52,7 @@ void print_cache_sb()
 	printf("/* %3.3lx */         	uint16_t	keys;\n", OFF_SB(keys));
 	printf("                  };\n");
 	printf("/* %3.3lx */         uint64_t		d[%u];\n", OFF_SB(d), SB_JOURNAL_BUCKETS);
+	printf("/* %3.3lx */         uint32_t		bucket_size_hi;\n", OFF_SB(bucket_size_hi));
 	printf("/* %3.3lx */ }\n", sizeof(struct cache_sb));
 }
 
-- 
2.26.2


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, back to index

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-05 16:04 [RFC PATCH 0/4] bcache-tools: changes for large bucket size Coly Li
2020-07-05 16:04 ` Coly Li
2020-07-05 16:04 ` [RFC PATCH 1/4] bcache-tools: comments offset for members of struct cache_sb Coly Li
2020-07-05 16:04 ` [RFC PATCH 2/4] struct_offset: print offset of each member of the on-disk data structure Coly Li
2020-07-05 16:04 ` [RFC PATCH 3/4] bcache-tools: The new super block version BCACHE_SB_VERSION_BDEV_WITH_FEATURES Coly Li
2020-07-05 16:04 ` [RFC PATCH 4/4] bcache-tools: add large_bucket incompat feature Coly Li
2020-07-05 16:04   ` Coly Li

Linux-bcache Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-bcache/0 linux-bcache/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-bcache linux-bcache/ https://lore.kernel.org/linux-bcache \
		linux-bcache@vger.kernel.org
	public-inbox-index linux-bcache

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-bcache


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git