diff --git a/0001-bcache-tools-set-zoned-size-aligned-data_offset-on-b.patch b/0001-bcache-tools-set-zoned-size-aligned-data_offset-on-b.patch new file mode 100644 index 0000000..2870c10 --- /dev/null +++ b/0001-bcache-tools-set-zoned-size-aligned-data_offset-on-b.patch @@ -0,0 +1,204 @@ +From 5042df018d651677e8a315bbf6b3bc654fdde5f2 Mon Sep 17 00:00:00 2001 +From: Coly Li +Date: Sat, 16 May 2020 19:55:12 +0800 +Subject: [PATCH 01/17] bcache-tools: set zoned size aligned data_offset on + backing device for zoned devive +Git-commit: 5042df018d651677e8a315bbf6b3bc654fdde5f2 +Patch-mainline: bcache-tools-1.1 +References: jsc#SLE-9807 + +If the backing device is a zoned device, e.g. host managed SMR hard +drive, the data_offset of the backing device should be set to a zone +size aligned value, this is necessary for the zoned device I/O LBA +and length requirement. + +This patch set the data_offset for zoned backing device by following +rules, +- If no manually inputed data_offset specified, set it to default + value: + - If BDEV_DATA_START_DEFAULT >= zone size and aligned to zone size, + keep data_offset as BDEV_DATA_START_DEFAULT. + - If BDEV_DATA_START_DEFAULT < zone size, set data_offset to zone + size. + - If data_offset is manually set, it must be a non-zero value aligned + to zone size. Of cause it can be multiple zones size, but must be + aligned to zone size. + +This patch also creates a new zone.c and zone.h and places all the +above zoned device related code there. + +Signed-off-by: Coly Li +--- + Makefile | 4 +-- + make.c | 7 ++++- + zoned.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + zoned.h | 13 +++++++++ + 4 files changed, 110 insertions(+), 3 deletions(-) + create mode 100644 zoned.c + create mode 100644 zoned.h + +diff --git a/Makefile b/Makefile +index 4359866..2c326cf 100644 +--- a/Makefile ++++ b/Makefile +@@ -24,7 +24,7 @@ bcache-test: LDLIBS += `pkg-config --libs openssl` -lm + + 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 ++make-bcache: make.o crc64.o lib.o zoned.o + + probe-bcache: LDLIBS += `pkg-config --libs uuid blkid` + probe-bcache: CFLAGS += `pkg-config --cflags uuid blkid` +@@ -38,4 +38,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 ++bcache: crc64.o lib.o make.o zoned.o +diff --git a/make.c b/make.c +index d46d925..c1090a6 100644 +--- a/make.c ++++ b/make.c +@@ -35,6 +35,7 @@ + #include "bcache.h" + #include "lib.h" + #include "bitwise.h" ++#include "zoned.h" + + #define max(x, y) ({ \ + typeof(x) _max1 = (x); \ +@@ -636,11 +637,15 @@ int make_bcache(int argc, char **argv) + cache_replacement_policy, + data_offset, set_uuid, false, force, label); + +- for (i = 0; i < nbacking_devices; i++) ++ for (i = 0; i < nbacking_devices; i++) { ++ check_data_offset_for_zoned_device(backing_devices[i], ++ &data_offset); ++ + write_sb(backing_devices[i], block_size, bucket_size, + writeback, discard, wipe_bcache, + cache_replacement_policy, + data_offset, set_uuid, true, force, label); ++ } + + return 0; + } +diff --git a/zoned.c b/zoned.c +new file mode 100644 +index 0000000..31c9136 +--- /dev/null ++++ b/zoned.c +@@ -0,0 +1,89 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * This file is part of bcache tools. ++ * Copyright (c) 2020 SUSE Software Solutions ++ * ++ * Authors: Coly Li ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "bcache.h" ++ ++/* ++ * copied and modified from zonefs_get_dev_capacity() of ++ * zonefs-tools. ++ * returns 0: zone size 0 indicates a non-zoned device ++ * > 0: actual zone size of the zoned device ++ */ ++static size_t get_zone_size(char *devname) ++{ ++ char str[128]; ++ FILE *file; ++ int res; ++ size_t zone_size = 0; ++ ++ snprintf(str, sizeof(str), ++ "/sys/block/%s/queue/chunk_sectors", ++ basename(devname)); ++ file = fopen(str, "r"); ++ if (!file) ++ goto out; ++ ++ memset(str, 0, sizeof(str)); ++ res = fscanf(file, "%s", str); ++ fclose(file); ++ ++ if (res != 1) ++ goto out; ++ ++ zone_size = atol(str); ++ ++out: ++ return zone_size; ++} ++ ++/* ++ * Update data_offset for zoned device, if the backing ++ * device is a zoned device, ++ * - just leave whole zone 0 to bcache super block on ++ * backing device. ++ * - if data_offset is specified and larger than ++ * BDEV_DATA_START_DEFAULT, then it should be a zone ++ * size aligned value. ++ */ ++void check_data_offset_for_zoned_device(char *devname, ++ uint64_t *data_offset) ++{ ++ uint64_t _data_offset = *data_offset; ++ size_t zone_size = get_zone_size(devname); ++ ++ if (!zone_size) ++ return; ++ ++ if (!_data_offset || ++ (_data_offset == BDEV_DATA_START_DEFAULT && ++ zone_size > BDEV_DATA_START_DEFAULT)) ++ _data_offset = zone_size; ++ ++ if (_data_offset < zone_size) { ++ fprintf(stderr, ++ "data_offset %lu should be larger than zone_size %lu for zoned device %s\n", ++ _data_offset, zone_size, devname); ++ exit(EXIT_FAILURE); ++ } ++ ++ if (_data_offset & (zone_size - 1)) { ++ fprintf(stderr, ++ "data_offset %lu is not aligned to zone size %lu for zoned device %s\n", ++ _data_offset, zone_size, devname); ++ } ++ ++ *data_offset = _data_offset; ++} +diff --git a/zoned.h b/zoned.h +new file mode 100644 +index 0000000..1c5cce8 +--- /dev/null ++++ b/zoned.h +@@ -0,0 +1,13 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * This file is part of bcache tools. ++ * Copyright (c) 2020 SUSE Software Solutions ++ * ++ * Authors: Coly Li ++ */ ++#ifndef __ZONED_H ++#define __ZONED_H ++ ++void check_data_offset_for_zoned_device(char *devname, uint64_t *data_offset); ++ ++#endif +-- +2.26.2 + diff --git a/0002-bcache-tools-add-is_zoned_device.patch b/0002-bcache-tools-add-is_zoned_device.patch new file mode 100644 index 0000000..12851b3 --- /dev/null +++ b/0002-bcache-tools-add-is_zoned_device.patch @@ -0,0 +1,44 @@ +From 0898a6c8899355b75a13bf490c09e21289d28478 Mon Sep 17 00:00:00 2001 +From: Coly Li +Date: Sat, 16 May 2020 21:46:29 +0800 +Subject: [PATCH 02/17] bcache-tools: add is_zoned_device() +Git-commit: 0898a6c8899355b75a13bf490c09e21289d28478 +Patch-mainline: bcache-tools-1.1 +References: jsc#SLE-9807 + +This is a wrapper of get_zone_size(), to check whether a device is +zoned device or not by checking its chunk_sectors. + +Signed-off-by: Coly Li +--- + zoned.c | 5 +++++ + zoned.h | 1 + + 2 files changed, 6 insertions(+) + +diff --git a/zoned.c b/zoned.c +index 31c9136..d078286 100644 +--- a/zoned.c ++++ b/zoned.c +@@ -87,3 +87,8 @@ void check_data_offset_for_zoned_device(char *devname, + + *data_offset = _data_offset; + } ++ ++int is_zoned_device(char *devname) ++{ ++ return (get_zone_size(devname) != 0); ++} +diff --git a/zoned.h b/zoned.h +index 1c5cce8..25e5c91 100644 +--- a/zoned.h ++++ b/zoned.h +@@ -9,5 +9,6 @@ + #define __ZONED_H + + void check_data_offset_for_zoned_device(char *devname, uint64_t *data_offset); ++int is_zoned_device(char *devname); + + #endif +-- +2.26.2 + diff --git a/0003-bcache-tools-convert-writeback-to-writethrough-mode-.patch b/0003-bcache-tools-convert-writeback-to-writethrough-mode-.patch new file mode 100644 index 0000000..a9a6b01 --- /dev/null +++ b/0003-bcache-tools-convert-writeback-to-writethrough-mode-.patch @@ -0,0 +1,50 @@ +From 33b90323056f65225c5b557d7f578b7f37abee3c Mon Sep 17 00:00:00 2001 +From: Coly Li +Date: Sat, 16 May 2020 21:57:17 +0800 +Subject: [PATCH 03/17] bcache-tools: convert writeback to writethrough mode + for zoned backing device +Git-commit: 33b90323056f65225c5b557d7f578b7f37abee3c +Patch-mainline: bcache-tools-1.1 +References: jsc#SLE-9807 + +Currently bcache does not support writeback cache mode for zoned device +as backing device. + +If the backing device is zoned device, and cache mode is explicitly set +to writeback mode, a information will be print to terminal, + "Zoned device detected: convert to writethrough mode." +Then the cache mode will be automatically converted to writethrough, +which is the default cache mode of bcache-tools. + +Signed-off-by: Coly Li +--- + make.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/make.c b/make.c +index c1090a6..cc76863 100644 +--- a/make.c ++++ b/make.c +@@ -378,6 +378,19 @@ static void write_sb(char *dev, unsigned int block_size, + SET_BDEV_CACHE_MODE(&sb, writeback ? + CACHE_MODE_WRITEBACK : CACHE_MODE_WRITETHROUGH); + ++ /* ++ * Currently bcache does not support writeback mode for ++ * zoned device as backing device. If the cache mode is ++ * explicitly set to writeback, automatically convert to ++ * writethough mode. ++ */ ++ if (is_zoned_device(dev) && ++ BDEV_CACHE_MODE(&sb) == CACHE_MODE_WRITEBACK) { ++ printf("Zoned device %s detected: convert to writethrough mode.\n\n", ++ dev); ++ SET_BDEV_CACHE_MODE(&sb, CACHE_MODE_WRITETHROUGH); ++ } ++ + if (data_offset != BDEV_DATA_START_DEFAULT) { + sb.version = BCACHE_SB_VERSION_BDEV_WITH_OFFSET; + sb.data_offset = data_offset; +-- +2.26.2 + diff --git a/0004-bcache-tools-add-struct-cache_sb_disk-into-bcache.h.patch b/0004-bcache-tools-add-struct-cache_sb_disk-into-bcache.h.patch new file mode 100644 index 0000000..1f368cc --- /dev/null +++ b/0004-bcache-tools-add-struct-cache_sb_disk-into-bcache.h.patch @@ -0,0 +1,93 @@ +From e46282f62364379a6c79b88afd5ed3b78c9781b7 Mon Sep 17 00:00:00 2001 +From: Coly Li +Date: Sun, 16 Aug 2020 21:45:28 +0800 +Subject: [PATCH 04/17] bcache-tools: add struct cache_sb_disk into bcache.h +Git-commit: e46282f62364379a6c79b88afd5ed3b78c9781b7 +Patch-mainline: bcache-tools-1.1 +References: jsc#SLE-9807 + +This is to sync the data structure from bcache kernel code uapi header. +The new added struct cache_sb_disk is used to define the on-disk format +bcache super block. Later struct cache_sb will be used for the in-memory +format bcache super block. + +Signed-off-by: Coly Li +--- + bcache.h | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 54 insertions(+) + +diff --git a/bcache.h b/bcache.h +index c83f838..82fe580 100644 +--- a/bcache.h ++++ b/bcache.h +@@ -7,6 +7,8 @@ + #ifndef _BCACHE_H + #define _BCACHE_H + ++#include ++ + #define BITMASK(name, type, field, offset, size) \ + static inline uint64_t name(const type *k) \ + { return (k->field >> offset) & ~(((uint64_t) ~0) << size); } \ +@@ -40,6 +42,58 @@ static const char bcache_magic[] = { + #define BDEV_DATA_START_DEFAULT 16 /* sectors */ + #define SB_START (SB_SECTOR * 512) + ++struct cache_sb_disk { ++ __le64 csum; ++ __le64 offset; /* sector where this sb was written */ ++ __le64 version; ++ ++ __u8 magic[16]; ++ ++ __u8 uuid[16]; ++ union { ++ __u8 set_uuid[16]; ++ __le64 set_magic; ++ }; ++ __u8 label[SB_LABEL_SIZE]; ++ ++ __le64 flags; ++ __le64 seq; ++ ++ __le64 pad[8]; ++ ++ union { ++ struct { ++ /* Cache devices */ ++ __le64 nbuckets; /* device size */ ++ ++ __le16 block_size; /* sectors */ ++ __le16 bucket_size; /* sectors */ ++ ++ __le16 nr_in_set; ++ __le16 nr_this_dev; ++ }; ++ struct { ++ /* Backing devices */ ++ __le64 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 ++ */ ++ }; ++ }; ++ ++ __le32 last_mount; /* time overflow in y2106 */ ++ ++ __le16 first_bucket; ++ union { ++ __le16 njournal_buckets; ++ __le16 keys; ++ }; ++ __le64 d[SB_JOURNAL_BUCKETS]; /* journal buckets */ ++}; ++ + struct cache_sb { + uint64_t csum; + uint64_t offset; /* sector where this sb was written */ +-- +2.26.2 + diff --git a/0005-bcache-tools-bitwise.h-more-swap-bitwise-for-differe.patch b/0005-bcache-tools-bitwise.h-more-swap-bitwise-for-differe.patch new file mode 100644 index 0000000..ba8aa80 --- /dev/null +++ b/0005-bcache-tools-bitwise.h-more-swap-bitwise-for-differe.patch @@ -0,0 +1,48 @@ +From 45d1412ee834b062a03b42596ee945d9916d3242 Mon Sep 17 00:00:00 2001 +From: Coly Li +Date: Sun, 16 Aug 2020 23:41:32 +0800 +Subject: [PATCH 05/17] bcache-tools: bitwise.h: more swap bitwise for + different CPU endians +Git-commit: 45d1412ee834b062a03b42596ee945d9916d3242 +Patch-mainline: bcache-tools-1.1 +References: jsc#SLE-9807 + +This patch adds more swap routines to bitwise.h, + le16_to_cpu() + le32_to_cpu() + le64_to_cpu() + +Signed-off-by: Coly Li +--- + bitwise.h | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/bitwise.h b/bitwise.h +index 968002f..1194b27 100644 +--- a/bitwise.h ++++ b/bitwise.h +@@ -45,11 +45,21 @@ + #define cpu_to_le16(val) ((__le16)(val)) + #define cpu_to_le32(val) ((__le32)(val)) + #define cpu_to_le64(val) ((__le64)(val)) ++ ++#define le16_to_cpu(val) ((__le16)(val)) ++#define le32_to_cpu(val) ((__le32)(val)) ++#define le64_to_cpu(val) ((__le64)(val)) ++ + #else + /* For big endian */ + #define cpu_to_le16(val) ((__be16)__swab16((__u16)(val))) + #define cpu_to_le32(val) ((__be32)__swab32((__u32)(val))) + #define cpu_to_le64(val) ((__be64)__swab64((__u64)(val))) ++ ++#define le16_to_cpu(val) ((__be16)__swab16((__u16)(val))) ++#define le32_to_cpu(val) ((__be32)__swab32((__u32)(val))) ++#define le64_to_cpu(val) ((__be64)__swab64((__u64)(val))) ++ + #endif + + #endif +-- +2.26.2 + diff --git a/0006-bcache-tools-list.h-only-define-offsetof-when-it-is-.patch b/0006-bcache-tools-list.h-only-define-offsetof-when-it-is-.patch new file mode 100644 index 0000000..fa3a7dc --- /dev/null +++ b/0006-bcache-tools-list.h-only-define-offsetof-when-it-is-.patch @@ -0,0 +1,40 @@ +From 1129319af1cb5ec0cd38b283a4a3d14e55d616c7 Mon Sep 17 00:00:00 2001 +From: Coly Li +Date: Sun, 16 Aug 2020 23:57:56 +0800 +Subject: [PATCH 06/17] bcache-tools: list.h: only define offsetof() when it is + undefined +Git-commit: 1129319af1cb5ec0cd38b283a4a3d14e55d616c7 +Patch-mainline: bcache-tools-1.1 +References: jsc#SLE-9807 + +For new gcc headers, offsetof() is defined, the definition in list.h +will be warned as redefined. + +This patch checks whether offsetof() is defined, and only defines local +version of offsetof() when it is not defined by gcc headers. + +Signed-off-by: Coly Li +--- + list.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/list.h b/list.h +index 55d2bb4..458281d 100644 +--- a/list.h ++++ b/list.h +@@ -25,10 +25,12 @@ + */ + /*@{*/ + ++#ifndef offsetof + /** + * Get offset of a member + */ + #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) ++#endif /* offsetof*/ + + /** + * Casts a member of a structure out to the containing structure +-- +2.26.2 + diff --git a/0007-bcache-tools-add-to_cache_sb-and-to_cache_sb_disk.patch b/0007-bcache-tools-add-to_cache_sb-and-to_cache_sb_disk.patch new file mode 100644 index 0000000..441ccac --- /dev/null +++ b/0007-bcache-tools-add-to_cache_sb-and-to_cache_sb_disk.patch @@ -0,0 +1,150 @@ +From 9642a1d29d8d1034039344bdd0cf55f71b5c16c8 Mon Sep 17 00:00:00 2001 +From: Coly Li +Date: Mon, 17 Aug 2020 00:02:23 +0800 +Subject: [PATCH 07/17] bcache-tools: add to_cache_sb() and to_cache_sb_disk() +Git-commit: 9642a1d29d8d1034039344bdd0cf55f71b5c16c8 +Patch-mainline: bcache-tools-1.1 +References: jsc#SLE-9807 + +This patch adds routines to_cache_sb() to_cache_sb_disk() to lib.c, +which convert bcache super block between in-memory and on-disk formats. + +This is a preparation to separate current struct cache_sb into two +structures, +- struct cache_sb is for in-memory super block +- struct cache_sb_disk is for on-disk super block + +Signed-off-by: Coly Li +--- + lib.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- + lib.h | 3 +- + 2 files changed, 90 insertions(+), 4 deletions(-) + +diff --git a/lib.c b/lib.c +index 9e69419..542f115 100644 +--- a/lib.c ++++ b/lib.c +@@ -8,14 +8,14 @@ + #include + #include + #include +-#include "bcache.h" +-#include "lib.h" + #include + #include + #include + #include + +- ++#include "bcache.h" ++#include "lib.h" ++#include "bitwise.h" + /* + * utils function + */ +@@ -681,3 +681,88 @@ int set_label(char *devname, char *label) + close(fd); + return 0; + } ++ ++ ++struct cache_sb *to_cache_sb(struct cache_sb *sb, ++ struct cache_sb_disk *sb_disk) ++{ ++ /* Convert common part */ ++ sb->offset = le64_to_cpu(sb_disk->offset); ++ sb->version = le64_to_cpu(sb_disk->version); ++ memcpy(sb->magic, sb_disk->magic, 16); ++ memcpy(sb->uuid, sb_disk->uuid, 16); ++ memcpy(sb->set_uuid, sb_disk->set_uuid, 16); ++ memcpy(sb->label, sb_disk->label, SB_LABEL_SIZE); ++ sb->flags = le64_to_cpu(sb_disk->flags); ++ sb->seq = le64_to_cpu(sb_disk->seq); ++ sb->block_size = le16_to_cpu(sb_disk->block_size); ++ sb->last_mount = le32_to_cpu(sb_disk->last_mount); ++ sb->first_bucket = le16_to_cpu(sb_disk->first_bucket); ++ sb->keys = le16_to_cpu(sb_disk->keys); ++ ++ /* For cache or backing devices*/ ++ ++ if (sb->version > BCACHE_SB_MAX_VERSION) { ++ /* Unsupported version */ ++ fprintf(stderr, "Unsupported super block version: %lld\n", ++ sb->version); ++ } else if (SB_IS_BDEV(sb)) { ++ /* Backing device */ ++ sb->data_offset = le64_to_cpu(sb_disk->data_offset); ++ } else { ++ int i; ++ ++ /* Cache device */ ++ sb->nbuckets = le64_to_cpu(sb_disk->nbuckets); ++ sb->nr_in_set = le16_to_cpu(sb_disk->nr_in_set); ++ sb->nr_this_dev = le16_to_cpu(sb_disk->nr_this_dev); ++ sb->bucket_size = le32_to_cpu(sb_disk->bucket_size); ++ ++ for (i = 0; i < SB_JOURNAL_BUCKETS; i++) ++ sb->d[i]= le64_to_cpu(sb_disk->d[i]); ++ } ++ ++ return sb; ++} ++ ++struct cache_sb_disk *to_cache_sb_disk(struct cache_sb_disk *sb_disk, ++ struct cache_sb *sb) ++{ ++ /* Convert common part */ ++ sb_disk->offset = cpu_to_le64(sb->offset); ++ sb_disk->version = cpu_to_le64(sb->version); ++ memcpy(sb_disk->magic, sb->magic, 16); ++ memcpy(sb_disk->uuid, sb->uuid, 16); ++ memcpy(sb_disk->set_uuid, sb->set_uuid, 16); ++ memcpy(sb_disk->label, sb->label, SB_LABEL_SIZE); ++ sb_disk->flags = cpu_to_le64(sb->flags); ++ sb_disk->seq = cpu_to_le64(sb->seq); ++ sb_disk->block_size = cpu_to_le16(sb->block_size); ++ sb_disk->last_mount = cpu_to_le32(sb->last_mount); ++ sb_disk->first_bucket = cpu_to_le16(sb->first_bucket); ++ sb_disk->keys = cpu_to_le16(sb->keys); ++ ++ /* For cache and backing devices */ ++ ++ if (sb->version > BCACHE_SB_MAX_VERSION) { ++ /* Unsupported version */ ++ fprintf(stderr, "Unsupported super block version: %lld\n", ++ sb->version); ++ } else if (SB_IS_BDEV(sb)) { ++ /* Backing device */ ++ sb_disk->data_offset = cpu_to_le64(sb->data_offset); ++ } else { ++ int i; ++ ++ /* Cache device */ ++ sb_disk->nbuckets = cpu_to_le64(sb->nbuckets); ++ sb_disk->nr_in_set = cpu_to_le16(sb->nr_in_set); ++ sb_disk->nr_this_dev = cpu_to_le16(sb->nr_this_dev); ++ sb_disk->bucket_size = cpu_to_le32(sb->bucket_size); ++ ++ for (i = 0; i < SB_JOURNAL_BUCKETS; i++) ++ sb_disk->d[i] = cpu_to_le64(sb->d[i]); ++ } ++ ++ return sb_disk; ++} +diff --git a/lib.h b/lib.h +index d4537b0..b37608e 100644 +--- a/lib.h ++++ b/lib.h +@@ -50,7 +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); +- ++struct cache_sb *to_cache_sb(struct cache_sb *sb, struct cache_sb_disk *sb_disk); ++struct cache_sb_disk *to_cache_sb_disk(struct cache_sb_disk *sb_disk,struct cache_sb *sb); + + #define DEVLEN sizeof(struct dev) + +-- +2.26.2 + diff --git a/0008-bcache-tools-define-separated-super-block-for-in-mem.patch b/0008-bcache-tools-define-separated-super-block-for-in-mem.patch new file mode 100644 index 0000000..ee764f1 --- /dev/null +++ b/0008-bcache-tools-define-separated-super-block-for-in-mem.patch @@ -0,0 +1,443 @@ +From 2891723d70759fb9d11cd74943ad72de9bfe092e Mon Sep 17 00:00:00 2001 +From: Coly Li +Date: Mon, 17 Aug 2020 00:15:26 +0800 +Subject: [PATCH 08/17] bcache-tools: define separated super block for + in-memory and on-disk format +Git-commit: 2891723d70759fb9d11cd74943ad72de9bfe092e +Patch-mainline: bcache-tools-1.1 +References: jsc#SLE-9807 + +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 +--- + Makefile | 2 +- + bcache-super-show.c | 22 +++++++++++-------- + bcache.h | 49 ++++++++++++++++++++++-------------------- + lib.c | 18 +++++++++++----- + make.c | 52 ++++++++++----------------------------------- + probe-bcache.c | 8 +++---- + 6 files changed, 68 insertions(+), 83 deletions(-) + +diff --git a/Makefile b/Makefile +index 2c326cf..b4546a1 100644 +--- a/Makefile ++++ b/Makefile +@@ -31,7 +31,7 @@ probe-bcache: CFLAGS += `pkg-config --cflags uuid blkid` + + 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 + + #include "bcache.h" +- ++#include "lib.h" ++#include "bitwise.h" + + static void usage() + { +@@ -61,6 +62,7 @@ int main(int argc, char **argv) + 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 @@ int main(int argc, char **argv) + 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 @@ int main(int argc, char **argv) + 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 @@ int main(int argc, char **argv) + 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 @@ int main(int argc, char **argv) + } + } + +- 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 @@ int main(int argc, char **argv) + 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 @@ struct cache_sb_disk { + __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 */ +- +- uint16_t block_size; /* sectors */ +- uint16_t bucket_size; /* sectors */ ++ __u64 nbuckets; /* device size */ + +- 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 @@ struct cache_sb { + }; + }; + +- 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 @@ int detail_base(char *devname, struct cache_sb sb, struct dev *base) + 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 detail_base(char *devname, struct cache_sb sb, struct dev *base) + + 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 @@ int may_add_item(char *devname, struct list_head *head) + + 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 may_add_item(char *devname, struct list_head *head) + 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 list_bdevs(struct list_head *head) + + 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 @@ int detail_dev(char *devname, struct bdev *bd, struct cdev *cd, int *type) + 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 @@ int detail_dev(char *devname, struct bdev *bd, struct cdev *cd, int *type) + 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 @@ 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, +@@ -261,9 +232,9 @@ static void write_sb(char *dev, unsigned int block_size, + { + 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 @@ static void write_sb(char *dev, unsigned int block_size, + 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 @@ static void write_sb(char *dev, unsigned int block_size, + 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 @@ 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); + +@@ -415,7 +385,7 @@ static void write_sb(char *dev, unsigned int block_size, + 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 @@ static void write_sb(char *dev, unsigned int block_size, + 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 @@ static void write_sb(char *dev, unsigned int block_size, + * 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 @@ int main(int argc, char **argv) + 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 @@ int main(int argc, char **argv) + 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" +-- +2.26.2 + diff --git a/0009-bcache-tools-upgrade-super-block-versions-for-featur.patch b/0009-bcache-tools-upgrade-super-block-versions-for-featur.patch new file mode 100644 index 0000000..80e0b28 --- /dev/null +++ b/0009-bcache-tools-upgrade-super-block-versions-for-featur.patch @@ -0,0 +1,228 @@ +From 5e7bd462ee91793708d6f0c34c46fb904bee7efb Mon Sep 17 00:00:00 2001 +From: Coly Li +Date: Mon, 17 Aug 2020 00:40:17 +0800 +Subject: [PATCH 09/17] bcache-tools: upgrade super block versions for feature + sets +Git-commit: 5e7bd462ee91793708d6f0c34c46fb904bee7efb +Patch-mainline: bcache-tools-1.1 +References: jsc#SLE-9807 + +This patch upgrades super block versions for adding feature sets into +struct cache_sb_disk, +128 __u64 feature_compat; +129 __u64 feature_incompat; +130 __u64 feature_ro_compat; + +With the feature set flags, it will be convenient to add new features +without upgrade super block version again (at least for a long time). + +The new added versions are, +- BCACHE_SB_VERSION_CDEV_WITH_FEATURES for cache device super block +- BCACHE_SB_VERSION_BDEV_WITH_FEATURES for backing device super block + +The feature set flags are also added into the in-memory super block +struct cache_sb. The feature sets conversion between cache_sb_disk and +cache_sb also added into to_cache_sb() and to_cache_sb_disk(). + +Some feature sets related macros are also added into bcache.h, and a new +file feature.c is added for future new features record and display. + +Signed-off-by: Coly Li +--- + Makefile | 2 +- + bcache.h | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- + features.c | 22 ++++++++++++++ + lib.c | 12 ++++++++ + 4 files changed, 118 insertions(+), 3 deletions(-) + create mode 100644 features.c + +diff --git a/Makefile b/Makefile +index b4546a1..8b87a67 100644 +--- a/Makefile ++++ b/Makefile +@@ -38,4 +38,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 250da9d..9d969e1 100644 +--- a/bcache.h ++++ b/bcache.h +@@ -29,12 +29,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 +@@ -59,7 +63,11 @@ struct cache_sb_disk { + __le64 flags; + __le64 seq; + +- __le64 pad[8]; ++ __le64 feature_compat; ++ __le64 feature_incompat; ++ __le64 feature_ro_compat; ++ ++ __le64 pad[5]; + + union { + struct { +@@ -116,6 +124,10 @@ struct cache_sb { + __u64 flags; + __u64 seq; + ++ __u64 feature_compat; ++ __u64 feature_incompat; ++ __u64 feature_ro_compat; ++ + union { + struct { + /* Cache devices */ +@@ -180,4 +192,73 @@ uint64_t crc64(const void *data, size_t len); + #define csum_set(i) \ + crc64(((void *) (i)) + 8, ((void *) end(i)) - (((void *) (i)) + 8)) + ++/* Feature set definition */ ++ ++#define BCH_FEATURE_COMPAT 0 ++#define BCH_FEATURE_RO_COMPAT 1 ++#define BCH_FEATURE_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)) ++ ++#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..a1c9884 +--- /dev/null ++++ b/features.c +@@ -0,0 +1,22 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Author: Coly Li ++ * ++ * Inspired by e2fsprogs features compat/incompat/ro_compat ++ * related code. ++ */ ++#include ++#include ++#include ++ ++#include "bcache.h" ++ ++struct feature { ++ int compat; ++ unsigned int mask; ++ const char *string; ++}; ++ ++static struct feature feature_list[] = { ++ {0, 0, 0 }, ++}; +diff --git a/lib.c b/lib.c +index 9a2fa26..dcf752c 100644 +--- a/lib.c ++++ b/lib.c +@@ -730,6 +730,12 @@ struct cache_sb *to_cache_sb(struct cache_sb *sb, + sb->d[i]= le64_to_cpu(sb_disk->d[i]); + } + ++ if (sb->version >= BCACHE_SB_VERSION_CDEV_WITH_FEATURES) { ++ sb->feature_compat = le64_to_cpu(sb_disk->feature_compat); ++ sb->feature_incompat = le64_to_cpu(sb_disk->feature_incompat); ++ sb->feature_ro_compat = le64_to_cpu(sb_disk->feature_ro_compat); ++ } ++ + return sb; + } + +@@ -772,5 +778,11 @@ struct cache_sb_disk *to_cache_sb_disk(struct cache_sb_disk *sb_disk, + sb_disk->d[i] = cpu_to_le64(sb->d[i]); + } + ++ if (sb->version >= BCACHE_SB_VERSION_CDEV_WITH_FEATURES) { ++ sb_disk->feature_compat = cpu_to_le64(sb->feature_compat); ++ sb_disk->feature_incompat = cpu_to_le64(sb->feature_incompat); ++ sb_disk->feature_ro_compat = cpu_to_le64(sb->feature_ro_compat); ++ } ++ + return sb_disk; + } +-- +2.26.2 + diff --git a/0010-bcache-tools-add-large_bucket-incompat-feature.patch b/0010-bcache-tools-add-large_bucket-incompat-feature.patch new file mode 100644 index 0000000..bc3bcec --- /dev/null +++ b/0010-bcache-tools-add-large_bucket-incompat-feature.patch @@ -0,0 +1,193 @@ +From 8c063851990a5e82ba1727907994a46201d9e842 Mon Sep 17 00:00:00 2001 +From: Coly Li +Date: Mon, 17 Aug 2020 01:37:17 +0800 +Subject: [PATCH 10/17] bcache-tools: add large_bucket incompat feature +Git-commit: 8c063851990a5e82ba1727907994a46201d9e842 +Patch-mainline: bcache-tools-1.1 +References: jsc#SLE-9807 + +This feature adds __le16 bucket_size_hi into struct cache_sb_disk, to +permit bucket size to be 32bit width. Current maximum bucket size is +16MB, 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 > 16MB, 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 +--- + bcache.h | 8 ++++++++ + features.c | 2 ++ + lib.c | 19 +++++++++++++++++++ + lib.h | 1 + + make.c | 18 ++++++++++++------ + 5 files changed, 42 insertions(+), 6 deletions(-) + +diff --git a/bcache.h b/bcache.h +index 9d969e1..6aef9c4 100644 +--- a/bcache.h ++++ b/bcache.h +@@ -100,6 +100,7 @@ struct cache_sb_disk { + __le16 keys; + }; + __le64 d[SB_JOURNAL_BUCKETS]; /* journal buckets */ ++ __le16 bucket_size_hi; + }; + + /* +@@ -210,6 +211,11 @@ uint64_t crc64(const void *data, size_t len); + #define BCH_HAS_INCOMPAT_FEATURE(sb, mask) \ + ((sb)->feature_incompat & (mask)) + ++/* 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) \ + { \ +@@ -261,4 +267,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 a1c9884..df15862 100644 +--- a/features.c ++++ b/features.c +@@ -18,5 +18,7 @@ struct feature { + }; + + static struct feature feature_list[] = { ++ {BCH_FEATURE_INCOMPAT, BCH_FEATURE_INCOMPAT_LARGE_BUCKET, ++ "large_bucket"}, + {0, 0, 0 }, + }; +diff --git a/lib.c b/lib.c +index dcf752c..efabeb1 100644 +--- a/lib.c ++++ b/lib.c +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -736,6 +737,10 @@ struct cache_sb *to_cache_sb(struct cache_sb *sb, + sb->feature_ro_compat = le64_to_cpu(sb_disk->feature_ro_compat); + } + ++ if (sb->version >= BCACHE_SB_VERSION_CDEV_WITH_FEATURES && ++ bch_has_feature_large_bucket(sb)) ++ sb->bucket_size += le16_to_cpu(sb_disk->bucket_size_hi) << 16; ++ + return sb; + } + +@@ -784,5 +789,19 @@ struct cache_sb_disk *to_cache_sb_disk(struct cache_sb_disk *sb_disk, + sb_disk->feature_ro_compat = cpu_to_le64(sb->feature_ro_compat); + } + ++ if (sb->version >= BCACHE_SB_VERSION_CDEV_WITH_FEATURES && ++ bch_has_feature_large_bucket(sb)) ++ sb_disk->bucket_size_hi = cpu_to_le16(sb->bucket_size >> 16); ++ + return sb_disk; + } ++ ++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 = bucket_size; ++} +diff --git a/lib.h b/lib.h +index b37608e..1dd2bfe 100644 +--- a/lib.h ++++ b/lib.h +@@ -52,6 +52,7 @@ int set_label(char *devname, char *label); + int cset_to_devname(struct list_head *head, char *cset, char *devname); + struct cache_sb *to_cache_sb(struct cache_sb *sb, struct cache_sb_disk *sb_disk); + struct cache_sb_disk *to_cache_sb_disk(struct cache_sb_disk *sb_disk,struct cache_sb *sb); ++void set_bucket_size(struct cache_sb *sb, unsigned int bucket_size); + + #define DEVLEN sizeof(struct dev) + +diff --git a/make.c b/make.c +index a239023..9631857 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); + } +@@ -338,7 +340,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); +@@ -362,7 +364,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; + } + +@@ -382,6 +385,7 @@ static void write_sb(char *dev, unsigned int block_size, + } else { + sb.nbuckets = getblocks(fd) / sb.bucket_size; + sb.nr_in_set = 1; ++ /* 23 is (SB_SECTOR + SB_SIZE) - 1 sectors */ + sb.first_bucket = (23 / sb.bucket_size) + 1; + + if (sb.nbuckets < 1 << 7) { +@@ -538,10 +542,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': +-- +2.26.2 + diff --git a/0011-bcache-tools-add-print_cache_set_supported_feature_s.patch b/0011-bcache-tools-add-print_cache_set_supported_feature_s.patch new file mode 100644 index 0000000..ff7480d --- /dev/null +++ b/0011-bcache-tools-add-print_cache_set_supported_feature_s.patch @@ -0,0 +1,270 @@ +From 047c4c4abdb49140ecf91d5e17624f2bf2535a69 Mon Sep 17 00:00:00 2001 +From: Coly Li +Date: Mon, 17 Aug 2020 19:23:10 +0800 +Subject: [PATCH 11/17] bcache-tools: add + print_cache_set_supported_feature_sets() in lib.c +Git-commit: 047c4c4abdb49140ecf91d5e17624f2bf2535a69 +Patch-mainline: bcache-tools-1.1 +References: jsc#SLE-9807 + +print_cache_set_supported_feature_sets() is used to print out feature +set strings for a specified cache device super block. It can be used +when make a bcache cache device, or show a super block information of +a bcache cache device. + +Signed-off-by: Coly Li +--- + bcache-super-show.c | 2 ++ + bcache.c | 15 +++++++++++--- + features.c | 50 +++++++++++++++++++++++++++++++++++++++++++++ + features.h | 8 ++++++++ + lib.c | 20 +++++++++++------- + lib.h | 4 ++++ + 6 files changed, 89 insertions(+), 10 deletions(-) + create mode 100644 features.h + +diff --git a/bcache-super-show.c b/bcache-super-show.c +index 883410f..cc36029 100644 +--- a/bcache-super-show.c ++++ b/bcache-super-show.c +@@ -134,12 +134,14 @@ int main(int argc, char **argv) + // These are handled the same by the kernel + case BCACHE_SB_VERSION_CDEV: + case BCACHE_SB_VERSION_CDEV_WITH_UUID: ++ case BCACHE_SB_VERSION_CDEV_WITH_FEATURES: + printf(" [cache device]\n"); + break; + + // The second adds data offset support + case BCACHE_SB_VERSION_BDEV: + case BCACHE_SB_VERSION_BDEV_WITH_OFFSET: ++ case BCACHE_SB_VERSION_BDEV_WITH_FEATURES: + printf(" [backing device]\n"); + break; + +diff --git a/bcache.c b/bcache.c +index b866271..50e3a88 100644 +--- a/bcache.c ++++ b/bcache.c +@@ -18,6 +18,7 @@ + #include "list.h" + #include + ++#include "features.h" + + #define BCACHE_TOOLS_VERSION "1.1" + +@@ -203,11 +204,13 @@ int show_bdevs_detail(void) + // These are handled the same by the kernel + case BCACHE_SB_VERSION_CDEV: + case BCACHE_SB_VERSION_CDEV_WITH_UUID: ++ case BCACHE_SB_VERSION_CDEV_WITH_FEATURES: + printf(" (cache)"); + break; + // The second adds data offset supporet + case BCACHE_SB_VERSION_BDEV: + case BCACHE_SB_VERSION_BDEV_WITH_OFFSET: ++ case BCACHE_SB_VERSION_BDEV_WITH_FEATURES: + printf(" (data)"); + break; + default: +@@ -257,12 +260,14 @@ int show_bdevs(void) + // These are handled the same by the kernel + case BCACHE_SB_VERSION_CDEV: + case BCACHE_SB_VERSION_CDEV_WITH_UUID: ++ case BCACHE_SB_VERSION_CDEV_WITH_FEATURES: + printf(" (cache)"); + break; + + // The second adds data offset supporet + case BCACHE_SB_VERSION_BDEV: + case BCACHE_SB_VERSION_BDEV_WITH_OFFSET: ++ case BCACHE_SB_VERSION_BDEV_WITH_FEATURES: + printf(" (data)"); + break; + +@@ -304,7 +309,9 @@ int detail_single(char *devname) + fprintf(stderr, "Failed to detail device\n"); + return ret; + } +- if (type == BCACHE_SB_VERSION_BDEV) { ++ if (type == BCACHE_SB_VERSION_BDEV || ++ type == BCACHE_SB_VERSION_BDEV_WITH_OFFSET || ++ type == BCACHE_SB_VERSION_BDEV_WITH_FEATURES) { + printf("sb.magic\t\t%s\n", bd.base.magic); + printf("sb.first_sector\t\t%" PRIu64 "\n", + bd.base.first_sector); +@@ -362,14 +369,16 @@ int detail_single(char *devname) + + putchar('\n'); + printf("cset.uuid\t\t%s\n", bd.base.cset); +- } else if (type == BCACHE_SB_VERSION_CDEV +- || type == BCACHE_SB_VERSION_CDEV_WITH_UUID) { ++ } else if (type == BCACHE_SB_VERSION_CDEV || ++ type == BCACHE_SB_VERSION_CDEV_WITH_UUID || ++ type == BCACHE_SB_VERSION_CDEV_WITH_FEATURES) { + printf("sb.magic\t\t%s\n", cd.base.magic); + printf("sb.first_sector\t\t%" PRIu64 "\n", + cd.base.first_sector); + printf("sb.csum\t\t\t%" PRIX64 "\n", cd.base.csum); + printf("sb.version\t\t%" PRIu64, cd.base.version); + printf(" [cache device]\n"); ++ print_cache_set_supported_feature_sets(&cd.base.sb); + putchar('\n'); + printf("dev.label\t\t"); + if (*cd.base.label) +diff --git a/features.c b/features.c +index df15862..181e348 100644 +--- a/features.c ++++ b/features.c +@@ -7,7 +7,9 @@ + */ + #include + #include ++#include + #include ++#include + + #include "bcache.h" + +@@ -22,3 +24,51 @@ static struct feature feature_list[] = { + "large_bucket"}, + {0, 0, 0 }, + }; ++ ++#define compose_feature_string(type, header) \ ++({ \ ++ struct feature *f; \ ++ bool first = true; \ ++ \ ++ for (f = &feature_list[0]; f->compat != 0; f++) { \ ++ if (f->compat != BCH_FEATURE_ ## type) \ ++ continue; \ ++ if (!(BCH_HAS_ ## type ## _FEATURE(sb, f->mask))) \ ++ continue; \ ++ \ ++ if (first) { \ ++ out += snprintf(out, buf + size - out, \ ++ "%s:\t", (header)); \ ++ first = false; \ ++ } else { \ ++ out += snprintf(out, buf + size - out, " "); \ ++ } \ ++ \ ++ out += snprintf(out, buf + size - out, "%s", f->string);\ ++ \ ++ } \ ++ if (!first) \ ++ out += snprintf(out, buf + size - out, "\n"); \ ++}) ++ ++void print_cache_set_supported_feature_sets(struct cache_sb *sb) ++{ ++ char buf[4096]; ++ char *out; ++ int size = sizeof(buf) - 1; ++ ++ out = buf; ++ memset(buf, 0, sizeof(buf)); ++ compose_feature_string(COMPAT, "sb.feature_compat"); ++ printf("%s", buf); ++ ++ out = buf; ++ memset(buf, 0, sizeof(buf)); ++ compose_feature_string(RO_COMPAT, "sb.feature_ro_compat"); ++ printf("%s", buf); ++ ++ out = buf; ++ memset(buf, 0, sizeof(buf)); ++ compose_feature_string(INCOMPAT, "sb.feature_incompat"); ++ printf("%s", buf); ++} +diff --git a/features.h b/features.h +new file mode 100644 +index 0000000..028b774 +--- /dev/null ++++ b/features.h +@@ -0,0 +1,8 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++ ++#ifndef _BCACHE_FEATURES_H ++#define _BCACHE_FEATURES_H ++ ++void print_cache_set_supported_feature_sets(struct cache_sb *sb); ++ ++#endif +diff --git a/lib.c b/lib.c +index efabeb1..29172f5 100644 +--- a/lib.c ++++ b/lib.c +@@ -192,11 +192,13 @@ int get_cachedev_state(char *cset_id, char *state) + + int get_state(struct dev *dev, char *state) + { +- if (dev->version == BCACHE_SB_VERSION_CDEV +- || dev->version == BCACHE_SB_VERSION_CDEV_WITH_UUID) ++ if (dev->version == BCACHE_SB_VERSION_CDEV || ++ dev->version == BCACHE_SB_VERSION_CDEV_WITH_UUID || ++ dev->version == BCACHE_SB_VERSION_CDEV_WITH_FEATURES) + return get_cachedev_state(dev->cset, state); +- else if (dev->version == BCACHE_SB_VERSION_BDEV +- || dev->version == BCACHE_SB_VERSION_BDEV_WITH_OFFSET) ++ else if (dev->version == BCACHE_SB_VERSION_BDEV || ++ dev->version == BCACHE_SB_VERSION_BDEV_WITH_OFFSET || ++ dev->version == BCACHE_SB_VERSION_BDEV_WITH_FEATURES) + return get_backdev_state(dev->name, state); + else + return 1; +@@ -291,6 +293,7 @@ int detail_base(char *devname, struct cache_sb sb, struct dev *base) + { + int ret; + ++ base->sb = sb; + strcpy(base->name, devname); + base->magic = "ok"; + base->first_sector = SB_SECTOR; +@@ -440,13 +443,16 @@ int detail_dev(char *devname, struct bdev *bd, struct cdev *cd, int *type) + } + + *type = sb.version; +- if (sb.version == BCACHE_SB_VERSION_BDEV) { ++ if (sb.version == BCACHE_SB_VERSION_BDEV || ++ sb.version == BCACHE_SB_VERSION_BDEV_WITH_OFFSET || ++ sb.version == BCACHE_SB_VERSION_BDEV_WITH_FEATURES) { + detail_base(devname, sb, &bd->base); + bd->first_sector = BDEV_DATA_START_DEFAULT; + bd->cache_mode = BDEV_CACHE_MODE(&sb); + bd->cache_state = BDEV_STATE(&sb); +- } else if (sb.version == BCACHE_SB_VERSION_CDEV +- || sb.version == BCACHE_SB_VERSION_CDEV_WITH_UUID) { ++ } else if (sb.version == BCACHE_SB_VERSION_CDEV || ++ sb.version == BCACHE_SB_VERSION_CDEV_WITH_UUID || ++ sb.version == BCACHE_SB_VERSION_CDEV_WITH_FEATURES) { + detail_base(devname, sb, &cd->base); + cd->first_sector = sb.bucket_size * sb.first_bucket; + cd->cache_sectors = +diff --git a/lib.h b/lib.h +index 1dd2bfe..9b5ed02 100644 +--- a/lib.h ++++ b/lib.h +@@ -4,6 +4,7 @@ + #include "list.h" + + struct dev { ++ struct cache_sb sb; + char name[40]; + char *magic; + uint64_t first_sector; +@@ -17,6 +18,9 @@ struct dev { + char state[40]; + char bname[40]; + char attachuuid[40]; ++ uint64_t feature_compat; ++ uint64_t feature_ro_compat; ++ uint64_t feature_incompat; + struct list_head dev_list; + }; + +-- +2.26.2 + diff --git a/0012-bcache-tools-Fix-potential-coredump-issues.patch b/0012-bcache-tools-Fix-potential-coredump-issues.patch new file mode 100644 index 0000000..ba94abd --- /dev/null +++ b/0012-bcache-tools-Fix-potential-coredump-issues.patch @@ -0,0 +1,99 @@ +From b0f5169a13976b05b183e0cde1fd23ef4f90101c Mon Sep 17 00:00:00 2001 +From: Shaoxiong Li +Date: Wed, 19 Aug 2020 18:51:26 +0800 +Subject: [PATCH 12/17] bcache-tools: Fix potential coredump issues +Git-commit: b0f5169a13976b05b183e0cde1fd23ef4f90101c +Patch-mainline: bcache-tools-1.1 +References: jsc#SLE-9807 + +In some distributions, such as opensuse 15.2, when the free_dev +function is called, it may refer to the memory that has been +released, causing a coredump. Changing 'list_for_each_entry' +to 'list_for_each_entry_safe' can avoid this problem. + +Signed-off-by: Shaoxiong Li +Signed-off-by: Coly Li +--- + bcache.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/bcache.c b/bcache.c +index 50e3a88..3b963e4 100644 +--- a/bcache.c ++++ b/bcache.c +@@ -175,9 +175,9 @@ int version_usagee(void) + + void free_dev(struct list_head *head) + { +- struct dev *dev; ++ struct dev *dev, *n; + +- list_for_each_entry(dev, head, dev_list) { ++ list_for_each_entry_safe(dev, n, head, dev_list) { + free(dev); + } + } +@@ -185,7 +185,7 @@ void free_dev(struct list_head *head) + int show_bdevs_detail(void) + { + struct list_head head; +- struct dev *devs; ++ struct dev *devs, *n; + + INIT_LIST_HEAD(&head); + int ret; +@@ -197,7 +197,7 @@ int show_bdevs_detail(void) + } + printf("Name\t\tUuid\t\t\t\t\tCset_Uuid\t\t\t\tType\t\tState"); + printf("\t\t\tBname\t\tAttachToDev\tAttachToCset\n"); +- list_for_each_entry(devs, &head, dev_list) { ++ list_for_each_entry_safe(devs, n, &head, dev_list) { + printf("%s\t%s\t%s\t%lu", devs->name, devs->uuid, + devs->cset, devs->version); + switch (devs->version) { +@@ -242,7 +242,7 @@ int show_bdevs_detail(void) + int show_bdevs(void) + { + struct list_head head; +- struct dev *devs; ++ struct dev *devs, *n; + + INIT_LIST_HEAD(&head); + int ret; +@@ -254,7 +254,7 @@ int show_bdevs(void) + } + + printf("Name\t\tType\t\tState\t\t\tBname\t\tAttachToDev\n"); +- list_for_each_entry(devs, &head, dev_list) { ++ list_for_each_entry_safe(devs, n, &head, dev_list) { + printf("%s\t%lu", devs->name, devs->version); + switch (devs->version) { + // These are handled the same by the kernel +@@ -428,7 +428,7 @@ int detail_single(char *devname) + int tree(void) + { + struct list_head head; +- struct dev *devs, *tmp; ++ struct dev *devs, *tmp, *n, *m; + + INIT_LIST_HEAD(&head); + int ret; +@@ -445,13 +445,13 @@ int tree(void) + tb = scols_new_table(); + scols_table_new_column(tb, ".", 0.1, SCOLS_FL_TREE); + scols_table_new_column(tb, "", 2, SCOLS_FL_TRUNC); +- list_for_each_entry(devs, &head, dev_list) { ++ list_for_each_entry_safe(devs, n, &head, dev_list) { + if ((devs->version == BCACHE_SB_VERSION_CDEV + || devs->version == BCACHE_SB_VERSION_CDEV_WITH_UUID) + && strcmp(devs->state, BCACHE_BASIC_STATE_ACTIVE) == 0) { + dad = scols_table_new_line(tb, NULL); + scols_line_set_data(dad, COL_CSET, devs->name); +- list_for_each_entry(tmp, &head, dev_list) { ++ list_for_each_entry_safe(tmp, m, &head, dev_list) { + if (strcmp(devs->cset, tmp->attachuuid) == + 0) { + son = +-- +2.26.2 + diff --git a/0013-bcache-tools-Export-CACHED_UUID-and-CACHED_LABEL.patch b/0013-bcache-tools-Export-CACHED_UUID-and-CACHED_LABEL.patch new file mode 100644 index 0000000..b4e8e5e --- /dev/null +++ b/0013-bcache-tools-Export-CACHED_UUID-and-CACHED_LABEL.patch @@ -0,0 +1,131 @@ +From 2cfea71ab753fc65f1d97b0af327e6e9e3fa204b Mon Sep 17 00:00:00 2001 +From: Ryan Harper +Date: Wed, 19 Aug 2020 18:51:27 +0800 +Subject: [PATCH 13/17] bcache-tools: Export CACHED_UUID and CACHED_LABEL +Git-commit: 2cfea71ab753fc65f1d97b0af327e6e9e3fa204b +Patch-mainline: bcache-tools-1.1 +References: jsc#SLE-9807 + +https://github.com/koverstreet/bcache-tools/pull/1 + +Add bcache-export-cached helper to export CACHED_UUID and CACHED_LABEL always + +Linux kernel bcache driver does not always emit a uevent[1] for when +a backing device is bound to a bcacheN device. When this happens, the udev +rule for creating /dev/bcache/by-uuid or /dev/bcache/by-label symlinks does +not fire and removes any persistent symlink to a specific backing device +since the bcache minor numbers (bcache0, 1, 2) are not guaranteed across reboots. + +This script reads the superblock of the bcache device slaves,ensuring the slave +is a backing device via sb.version check, extracts the dev.uuid and +dev.label values and exports them to udev for triggering the symlink rules in +the existing rules file. + +1. https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1729145 + +Signed-off-by: Shaoxiong Li +Signed-off-by: Coly Li +--- + 69-bcache.rules | 7 +++---- + Makefile | 2 +- + bcache-export-cached | 31 +++++++++++++++++++++++++++++++ + initcpio/install | 1 + + initramfs/hook | 1 + + 5 files changed, 37 insertions(+), 5 deletions(-) + create mode 100644 bcache-export-cached + +diff --git a/69-bcache.rules b/69-bcache.rules +index 9cc7f0d..fd25f5b 100644 +--- a/69-bcache.rules ++++ b/69-bcache.rules +@@ -23,10 +23,9 @@ RUN+="bcache-register $tempnode" + LABEL="bcache_backing_end" + + # Cached devices: symlink +-DRIVER=="bcache", ENV{CACHED_UUID}=="?*", \ +- SYMLINK+="bcache/by-uuid/$env{CACHED_UUID}" +-DRIVER=="bcache", ENV{CACHED_LABEL}=="?*", \ +- SYMLINK+="bcache/by-label/$env{CACHED_LABEL}" ++IMPORT{program}="bcache-export-cached $tempnode" ++ENV{CACHED_UUID}=="?*", SYMLINK+="bcache/by-uuid/$env{CACHED_UUID}" ++ENV{CACHED_LABEL}=="?*", SYMLINK+="bcache/by-label/$env{CACHED_LABEL}" + + LABEL="bcache_end" + +diff --git a/Makefile b/Makefile +index 8b87a67..90db951 100644 +--- a/Makefile ++++ b/Makefile +@@ -9,7 +9,7 @@ all: make-bcache probe-bcache bcache-super-show bcache-register bcache + + install: make-bcache probe-bcache bcache-super-show + $(INSTALL) -m0755 make-bcache bcache-super-show bcache $(DESTDIR)${PREFIX}/sbin/ +- $(INSTALL) -m0755 probe-bcache bcache-register $(DESTDIR)$(UDEVLIBDIR)/ ++ $(INSTALL) -m0755 probe-bcache bcache-register bcache-export-cached $(DESTDIR)$(UDEVLIBDIR)/ + $(INSTALL) -m0644 69-bcache.rules $(DESTDIR)$(UDEVLIBDIR)/rules.d/ + $(INSTALL) -m0644 -- *.8 $(DESTDIR)${PREFIX}/share/man/man8/ + $(INSTALL) -D -m0755 initramfs/hook $(DESTDIR)/usr/share/initramfs-tools/hooks/bcache +diff --git a/bcache-export-cached b/bcache-export-cached +new file mode 100644 +index 0000000..b345922 +--- /dev/null ++++ b/bcache-export-cached +@@ -0,0 +1,31 @@ ++#!/bin/sh ++# ++# This program reads the bcache superblock on bcacheX slaves to extract the ++# dev.uuid and dev.label which refer to a specific backing device. ++# ++# It integrates with udev 'import' by writing CACHED_UUID=X and optionally ++# CACHED_LABEL=X for the backing device of the provided bcache device. ++# Ignore caching devices by skipping unless sb.version=1 ++# ++# There is 1 and only 1 backing device (slaves/*) for a bcache device. ++ ++TEMPNODE=${1} # /dev/bcacheN ++DEVNAME=${TEMPNODE##*/} # /dev/bcacheN -> bcacheN ++ ++for slave in "/sys/class/block/$DEVNAME/slaves"/*; do ++ [ -d "$slave" ] || continue ++ bcache-super-show "/dev/${slave##*/}" | ++ awk '$1 == "sb.version" { sbver=$2; } ++ $1 == "dev.uuid" { uuid=$2; } ++ $1 == "dev.label" && $2 != "(empty)" { label=$2; } ++ END { ++ if (sbver == 1 && uuid) { ++ print("CACHED_UUID=" uuid) ++ if (label) print("CACHED_LABEL=" label) ++ exit(0) ++ } ++ exit(1); ++ }' ++ # awk exits 0 if it found a backing device. ++ [ $? -eq 0 ] && exit 0 ++done +diff --git a/initcpio/install b/initcpio/install +index 72d4231..c1a86fe 100755 +--- a/initcpio/install ++++ b/initcpio/install +@@ -1,6 +1,7 @@ + #!/bin/bash + build() { + add_module bcache ++ add_binary /usr/lib/udev/bcache-export-cached + add_binary /usr/lib/udev/bcache-register + add_binary /usr/lib/udev/probe-bcache + add_file /usr/lib/udev/rules.d/69-bcache.rules +diff --git a/initramfs/hook b/initramfs/hook +index a6baa24..485491d 100755 +--- a/initramfs/hook ++++ b/initramfs/hook +@@ -22,6 +22,7 @@ elif [ -e /lib/udev/rules.d/69-bcache.rules ]; then + cp -pt "${DESTDIR}/lib/udev/rules.d" /lib/udev/rules.d/69-bcache.rules + fi + ++copy_exec /lib/udev/bcache-export-cached + copy_exec /lib/udev/bcache-register + copy_exec /lib/udev/probe-bcache + manual_add_modules bcache +-- +2.26.2 + diff --git a/0014-bcache-tools-Remove-the-dependency-on-libsmartcols.patch b/0014-bcache-tools-Remove-the-dependency-on-libsmartcols.patch new file mode 100644 index 0000000..b064f62 --- /dev/null +++ b/0014-bcache-tools-Remove-the-dependency-on-libsmartcols.patch @@ -0,0 +1,150 @@ +From 38726cd652e3a3b75f2ae26f8b73e05dff7ed662 Mon Sep 17 00:00:00 2001 +From: Shaoxiong Li +Date: Wed, 19 Aug 2020 18:51:28 +0800 +Subject: [PATCH 14/17] bcache-tools: Remove the dependency on libsmartcols +Git-commit: 38726cd652e3a3b75f2ae26f8b73e05dff7ed662 +Patch-mainline: bcache-tools-1.1 +References: jsc#SLE-9807 + +The bcache tree function relies on the libsmartcols library to +display the relationship between the cache device and the bdev +device in a tree shape. However, it is difficult for many old +operating systems (such as Ubuntu 12) to install this library. + +For better compatibility, a simpler implementation is used to +achieve the same purpose, while removing the dependency on +libsmartcols. + +Signed-off-by: Shaoxiong Li +Signed-off-by: Coly Li +--- + Makefile | 8 ++++---- + bcache.c | 53 +++++++++++++++++++++++++++++++++++------------------ + 2 files changed, 39 insertions(+), 22 deletions(-) + +diff --git a/Makefile b/Makefile +index 90db951..df44085 100644 +--- a/Makefile ++++ b/Makefile +@@ -22,8 +22,8 @@ clean: + + bcache-test: LDLIBS += `pkg-config --libs openssl` -lm + +-make-bcache: LDLIBS += `pkg-config --libs uuid blkid smartcols` +-make-bcache: CFLAGS += `pkg-config --cflags uuid blkid smartcols` ++make-bcache: LDLIBS += `pkg-config --libs uuid blkid` ++make-bcache: CFLAGS += `pkg-config --cflags uuid blkid` + make-bcache: make.o crc64.o lib.o zoned.o + + probe-bcache: LDLIBS += `pkg-config --libs uuid blkid` +@@ -35,7 +35,7 @@ bcache-super-show: crc64.o lib.o + + bcache-register: bcache-register.o + +-bcache: CFLAGS += `pkg-config --cflags blkid uuid smartcols` +-bcache: LDLIBS += `pkg-config --libs blkid uuid smartcols` ++bcache: CFLAGS += `pkg-config --cflags blkid uuid` ++bcache: LDLIBS += `pkg-config --libs blkid uuid` + bcache: CFLAGS += -std=gnu99 + bcache: crc64.o lib.o make.o zoned.o features.o +diff --git a/bcache.c b/bcache.c +index 3b963e4..a0c5a67 100644 +--- a/bcache.c ++++ b/bcache.c +@@ -10,13 +10,13 @@ + #include + #include + #include +-#include + #include "bcache.h" + #include "lib.h" + #include "make.h" + #include + #include "list.h" + #include ++#include + + #include "features.h" + +@@ -425,8 +425,34 @@ int detail_single(char *devname) + return 0; + } + ++void replace_line(char **dest, const char *from, const char *to) ++{ ++ assert(strlen(from) == strlen(to)); ++ char sub[4096] = ""; ++ char new[4096] = ""; ++ ++ strcpy(sub, *dest); ++ while (1) { ++ char *tmp = strpbrk(sub, from); ++ ++ if (tmp != NULL) { ++ strcpy(new, tmp); ++ strcpy(sub, tmp + strlen(from)); ++ } else ++ break; ++ } ++ if (strlen(new) > 0) { ++ strncpy(new, to, strlen(to)); ++ sprintf(*dest + strlen(*dest) - strlen(new), new, strlen(new)); ++ } ++} ++ + int tree(void) + { ++ char *out = (char *)malloc(4096); ++ const char *begin = ".\n"; ++ const char *middle = "├─"; ++ const char *tail = "└─"; + struct list_head head; + struct dev *devs, *tmp, *n, *m; + +@@ -438,35 +464,26 @@ int tree(void) + fprintf(stderr, "Failed to list devices\n"); + return ret; + } +- struct libscols_table *tb; +- struct libscols_line *dad, *son; +- enum { COL_CSET, COL_BNAME }; +- setlocale(LC_ALL, ""); +- tb = scols_new_table(); +- scols_table_new_column(tb, ".", 0.1, SCOLS_FL_TREE); +- scols_table_new_column(tb, "", 2, SCOLS_FL_TRUNC); ++ sprintf(out, "%s", begin); + list_for_each_entry_safe(devs, n, &head, dev_list) { + if ((devs->version == BCACHE_SB_VERSION_CDEV + || devs->version == BCACHE_SB_VERSION_CDEV_WITH_UUID) + && strcmp(devs->state, BCACHE_BASIC_STATE_ACTIVE) == 0) { +- dad = scols_table_new_line(tb, NULL); +- scols_line_set_data(dad, COL_CSET, devs->name); ++ sprintf(out + strlen(out), "%s\n", devs->name); + list_for_each_entry_safe(tmp, m, &head, dev_list) { + if (strcmp(devs->cset, tmp->attachuuid) == + 0) { +- son = +- scols_table_new_line(tb, dad); +- scols_line_set_data(son, COL_CSET, +- tmp->name); +- scols_line_set_data(son, COL_BNAME, +- tmp->bname); ++ replace_line(&out, tail, middle); ++ sprintf(out + strlen(out), "%s%s %s\n", ++ tail, tmp->name, tmp->bname); + } + } + } + } +- scols_print_table(tb); +- scols_unref_table(tb); ++ if (strlen(out) > strlen(begin)) ++ printf("%s", out); + free_dev(&head); ++ free(out); + return 0; + } + +-- +2.26.2 + diff --git a/0015-bcache-tools-make-permit-only-one-cache-device-to-be.patch b/0015-bcache-tools-make-permit-only-one-cache-device-to-be.patch new file mode 100644 index 0000000..98bb5ed --- /dev/null +++ b/0015-bcache-tools-make-permit-only-one-cache-device-to-be.patch @@ -0,0 +1,40 @@ +From 67163cc86255bb93d524051e488de15172ab396c Mon Sep 17 00:00:00 2001 +From: Coly Li +Date: Sun, 23 Aug 2020 00:26:31 +0800 +Subject: [PATCH 15/17] bcache-tools: make: permit only one cache device to be + specified +Git-commit: 67163cc86255bb93d524051e488de15172ab396c +Patch-mainline: bcache-tools-1.1 +References: jsc#SLE-9807 + +Now a cache set only has a single cache, therefore "bcache make" should +permit only one cache device to be specified for a cache set. + +This patch checks if more than one cache devices are specified by "-C" +an error message "Please specify only one cache device" will be printed +and bcache exits with usage information. + +Signed-off-by: Coly Li +--- + make.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/make.c b/make.c +index 9631857..ad89377 100644 +--- a/make.c ++++ b/make.c +@@ -604,6 +604,11 @@ int make_bcache(int argc, char **argv) + usage(); + } + ++ if (ncache_devices > 1) { ++ fprintf(stderr, "Please specify only one cache device\n"); ++ usage(); ++ } ++ + if (bucket_size < block_size) { + fprintf(stderr, + "Bucket size cannot be smaller than block size\n"); +-- +2.26.2 + diff --git a/0016-bcache-tools-add-bcache-status.patch b/0016-bcache-tools-add-bcache-status.patch new file mode 100644 index 0000000..f2642fe --- /dev/null +++ b/0016-bcache-tools-add-bcache-status.patch @@ -0,0 +1,384 @@ +From 10824170800268e91508e2edc6ed745f40370f0a Mon Sep 17 00:00:00 2001 +From: Coly Li +Date: Wed, 2 Sep 2020 19:27:08 +0800 +Subject: [PATCH 16/17] bcache-tools: add bcache-status +Git-commit: 10824170800268e91508e2edc6ed745f40370f0a +Patch-mainline: bcache-tools-1.1 +References: jsc#SLE-9807 + +People request to include bcache-status into bcache-tools package. This +patch picks bcache-status script from github page of the orginal author +Darrick J. Wong, + https://github.com/djwong/bcache-tools/blob/master/bcache-status + +Thanks to Darrick for writing the great bcache-status, and I will keep +this script being updated from Darrick's repo time to time. + +Signed-off-by: Coly Li +Cc: Darrick J. Wong +--- + bcache-status | 352 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 352 insertions(+) + create mode 100755 bcache-status + +diff --git a/bcache-status b/bcache-status +new file mode 100755 +index 0000000..ac5a22f +--- /dev/null ++++ b/bcache-status +@@ -0,0 +1,352 @@ ++#!/usr/bin/env python ++# ++# Dumb script to dump (some) of bcache status ++# Copyright 2014 Darrick J. Wong. All rights reserved. ++# ++# This file is part of Bcache. Bcache is free software: you can ++# redistribute it and/or modify it under the terms of the GNU General Public ++# License as published by the Free Software Foundation, version 2. ++# ++# This program is distributed in the hope that it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ++# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more ++# details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., 51 ++# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++import os ++import sys ++import argparse ++ ++MAX_KEY_LENGTH = 28 ++DEV_BLOCK_PATH = '/dev/block/' ++SYSFS_BCACHE_PATH = '/sys/fs/bcache/' ++SYSFS_BLOCK_PATH = '/sys/block/' ++ ++def file_to_lines(fname): ++ try: ++ with open(fname, "r") as fd: ++ return fd.readlines() ++ except: ++ return [] ++ ++def file_to_line(fname): ++ ret = file_to_lines(fname) ++ if ret: ++ return ret[0].strip() ++ return '' ++ ++def str_to_bool(x): ++ return x == '1' ++ ++def format_sectors(x): ++ '''Pretty print a sector count.''' ++ sectors = float(x) ++ asectors = abs(sectors) ++ ++ if asectors < 2: ++ return '%d B' % (sectors * 512) ++ elif asectors < 2048: ++ return '%.2f KiB' % (sectors / 2) ++ elif asectors < 2097152: ++ return '%.1f MiB' % (sectors / 2048) ++ elif asectors < 2147483648: ++ return '%.0f GiB' % (sectors / 2097152) ++ else: ++ return '%.0f TiB' % (sectors / 2147483648) ++ ++def interpret_sectors(x): ++ '''Interpret a pretty-printed disk size.''' ++ factors = { ++ 'k': 1 << 10, ++ 'M': 1 << 20, ++ 'G': 1 << 30, ++ 'T': 1 << 40, ++ 'P': 1 << 50, ++ 'E': 1 << 60, ++ 'Z': 1 << 70, ++ 'Y': 1 << 80, ++ } ++ ++ factor = 1 ++ if x[-1] in factors: ++ factor = factors[x[-1]] ++ x = x[:-1] ++ return int(float(x) * factor / 512) ++ ++def pretty_size(x): ++ return format_sectors(interpret_sectors(x)) ++ ++def device_path(x): ++ if not os.path.isdir(DEV_BLOCK_PATH): ++ return '?' ++ x = '%s/%s' % (DEV_BLOCK_PATH, x) ++ return os.path.abspath(os.path.join(os.path.dirname(x), os.readlink(x))) ++ ++def str_device_path(x): ++ return '%s (%s)' % (device_path(x), x) ++ ++def dump_bdev(bdev_path): ++ '''Dump a backing device stats.''' ++ global MAX_KEY_LENGTH ++ attrs = [ ++ ('../dev', 'Device File', str_device_path), ++ ('dev/dev', 'bcache Device File', str_device_path), ++ ('../size', 'Size', format_sectors), ++ ('cache_mode', 'Cache Mode', None), ++ ('readahead', 'Readahead', None), ++ ('sequential_cutoff', 'Sequential Cutoff', pretty_size), ++ ('sequential_merge', 'Merge sequential?', str_to_bool), ++ ('state', 'State', None), ++ ('writeback_running', 'Writeback?', str_to_bool), ++ ('dirty_data', 'Dirty Data', pretty_size), ++ ('writeback_rate', 'Writeback Rate', lambda x: '%s/s' % x), ++ ('writeback_percent', 'Dirty Target', lambda x: '%s%%' % x), ++ ] ++ ++ print('--- Backing Device ---') ++ for (sysfs_name, display_name, conversion_func) in attrs: ++ val = file_to_line('%s/%s' % (bdev_path, sysfs_name)) ++ if conversion_func is not None: ++ val = conversion_func(val) ++ if display_name is None: ++ display_name = sysfs_name ++ print(' %-*s%s' % (MAX_KEY_LENGTH - 2, display_name, val)) ++ ++def dump_cachedev(cachedev_path): ++ '''Dump a cachding device stats.''' ++ def fmt_cachesize(val): ++ return '%s\t(%.0f%%)' % (format_sectors(val), float(val) / cache_size * 100) ++ ++ global MAX_KEY_LENGTH ++ attrs = [ ++ ('../dev', 'Device File', str_device_path), ++ ('../size', 'Size', format_sectors), ++ ('block_size', 'Block Size', pretty_size), ++ ('bucket_size', 'Bucket Size', pretty_size), ++ ('cache_replacement_policy', 'Replacement Policy', None), ++ ('discard', 'Discard?', str_to_bool), ++ ('io_errors', 'I/O Errors', None), ++ ('metadata_written', 'Metadata Written', pretty_size), ++ ('written', 'Data Written', pretty_size), ++ ('nbuckets', 'Buckets', None), ++ (None, 'Cache Used', lambda x: fmt_cachesize(used_sectors)), ++ (None, 'Cache Unused', lambda x: fmt_cachesize(unused_sectors)), ++ ] ++ ++ stats = get_cache_priority_stats(cachedev_path) ++ cache_size = int(file_to_line('%s/../size' % cachedev_path)) ++ unused_sectors = float(stats['Unused'][:-1]) * cache_size / 100 ++ used_sectors = cache_size - unused_sectors ++ ++ print('--- Cache Device ---') ++ for (sysfs_name, display_name, conversion_func) in attrs: ++ if sysfs_name is not None: ++ val = file_to_line('%s/%s' % (cachedev_path, sysfs_name)) ++ if conversion_func is not None: ++ val = conversion_func(val) ++ if display_name is None: ++ display_name = sysfs_name ++ print(' %-*s%s' % (MAX_KEY_LENGTH - 2, display_name, val)) ++ ++def hits_to_str(hits_str, misses_str): ++ '''Render a hits/misses ratio as a string.''' ++ hits = int(hits_str) ++ misses = int(misses_str) ++ ++ ret = '%d' % hits ++ if hits + misses != 0: ++ ret = '%s\t(%.d%%)' % (ret, 100 * hits / (hits + misses)) ++ return ret ++ ++def dump_stats(sysfs_path, indent_str, stats): ++ '''Dump stats on a bcache device.''' ++ stat_types = [ ++ ('five_minute', 'Last 5min'), ++ ('hour', 'Last Hour'), ++ ('day', 'Last Day'), ++ ('total', 'Total'), ++ ] ++ attrs = ['bypassed', 'cache_bypass_hits', 'cache_bypass_misses', 'cache_hits', 'cache_misses'] ++ display = [ ++ ('Hits', lambda: hits_to_str(stat_data['cache_hits'], stat_data['cache_misses'])), ++ ('Misses', lambda: stat_data['cache_misses']), ++ ('Bypass Hits', lambda: hits_to_str(stat_data['cache_bypass_hits'], stat_data['cache_bypass_misses'])), ++ ('Bypass Misses', lambda: stat_data['cache_bypass_misses']), ++ ('Bypassed', lambda: pretty_size(stat_data['bypassed'])), ++ ] ++ ++ for (sysfs_name, stat_display_name) in stat_types: ++ if len(stats) > 0 and sysfs_name not in stats: ++ continue ++ stat_data = {} ++ for attr in attrs: ++ val = file_to_line('%s/stats_%s/%s' % (sysfs_path, sysfs_name, attr)) ++ stat_data[attr] = val ++ for (display_name, str_func) in display: ++ d = '%s%s %s' % (indent_str, stat_display_name, display_name) ++ print('%-*s%s' % (MAX_KEY_LENGTH, d, str_func())) ++ ++def get_cache_priority_stats(cache): ++ '''Retrieve priority stats from a cache.''' ++ attrs = {} ++ ++ for line in file_to_lines('%s/priority_stats' % cache): ++ x = line.split() ++ key = x[0] ++ value = x[1] ++ attrs[key[:-1]] = value ++ return attrs ++ ++def dump_bcache(bcache_sysfs_path, stats, print_subdevices, device): ++ '''Dump bcache stats''' ++ def fmt_cachesize(val): ++ return '%s\t(%.0f%%)' % (format_sectors(val), 100.0 * val / cache_sectors) ++ ++ attrs = [ ++ (None, 'UUID', lambda x: os.path.basename(bcache_sysfs_path)), ++ ('block_size', 'Block Size', pretty_size), ++ ('bucket_size', 'Bucket Size', pretty_size), ++ ('congested', 'Congested?', str_to_bool), ++ ('congested_read_threshold_us', 'Read Congestion', lambda x: '%.1fms' % (int(x) / 1000)), ++ ('congested_write_threshold_us', 'Write Congestion', lambda x: '%.1fms' % (int(x) / 1000)), ++ (None, 'Total Cache Size', lambda x: format_sectors(cache_sectors)), ++ (None, 'Total Cache Used', lambda x: fmt_cachesize(cache_used_sectors)), ++ (None, 'Total Cache Unused', lambda x: fmt_cachesize(cache_unused_sectors)), ++ #('dirty_data', 'Dirty Data', lambda x: fmt_cachesize(interpret_sectors(x))), # disappeared in 3.13? ++ ('cache_available_percent', 'Evictable Cache', lambda x: '%s\t(%s%%)' % (format_sectors(float(x) * cache_sectors / 100), x)), ++ (None, 'Replacement Policy', lambda x: replacement_policies.pop() if len(replacement_policies) == 1 else '(Various)'), ++ (None, 'Cache Mode', lambda x: cache_modes.pop() if len(cache_modes) == 1 else '(Various)'), ++ ] ++ ++ # Calculate aggregate data ++ cache_sectors = 0 ++ cache_unused_sectors = 0 ++ cache_modes = set() ++ replacement_policies = set() ++ for obj in os.listdir(bcache_sysfs_path): ++ if not os.path.isdir('%s/%s' % (bcache_sysfs_path, obj)): ++ continue ++ if obj.startswith('cache'): ++ cache_size = int(file_to_line('%s/%s/../size' % (bcache_sysfs_path, obj))) ++ cache_sectors += cache_size ++ cstats = get_cache_priority_stats('%s/%s' % (bcache_sysfs_path, obj)) ++ unused_size = float(cstats['Unused'][:-1]) * cache_size / 100 ++ cache_unused_sectors += unused_size ++ replacement_policies.add(file_to_line('%s/%s/cache_replacement_policy' % (bcache_sysfs_path, obj))) ++ elif obj.startswith('bdev'): ++ cache_modes.add(file_to_line('%s/%s/cache_mode' % (bcache_sysfs_path, obj))) ++ cache_used_sectors = cache_sectors - cache_unused_sectors ++ ++ # Dump basic stats ++ print("--- bcache ---") ++ for (sysfs_name, display_name, conversion_func) in attrs: ++ if sysfs_name is not None: ++ val = file_to_line('%s/%s' % (bcache_sysfs_path, sysfs_name)) ++ else: ++ val = None ++ if conversion_func is not None: ++ val = conversion_func(val) ++ if display_name is None: ++ display_name = sysfs_name ++ print('%-*s%s' % (MAX_KEY_LENGTH, display_name, val)) ++ dump_stats(bcache_sysfs_path, '', stats) ++ ++ # Dump sub-device stats ++ if not print_subdevices: ++ return ++ for obj in os.listdir(bcache_sysfs_path): ++ if not os.path.isdir('%s/%s' % (bcache_sysfs_path, obj)): ++ continue ++ if obj.startswith('bdev'): ++ dump_bdev('%s/%s' % (bcache_sysfs_path, obj)) ++ dump_stats('%s/%s' % (bcache_sysfs_path, obj), ' ', stats) ++ elif obj.startswith('cache'): ++ dump_cachedev('%s/%s' % (bcache_sysfs_path, obj)) ++ ++def map_uuid_to_device(): ++ '''Map bcache UUIDs to device files.''' ++ global SYSFS_BLOCK_PATH ++ ret = {} ++ ++ if not os.path.isdir(SYSFS_BLOCK_PATH): ++ return ret ++ for bdev in os.listdir(SYSFS_BLOCK_PATH): ++ link = '%s%s/bcache/cache' % (SYSFS_BLOCK_PATH, bdev) ++ if not os.path.islink(link): ++ continue ++ basename = os.path.basename(os.readlink(link)) ++ ret[basename] = file_to_line('%s%s/dev' % (SYSFS_BLOCK_PATH, bdev)) ++ return ret ++ ++def main(): ++ '''Main function''' ++ global SYSFS_BCACHE_PATH ++ global uuid_map ++ stats = set() ++ reset_stats = False ++ print_subdevices = False ++ run_gc = False ++ ++ parser = argparse.ArgumentParser(add_help=False) ++ parser.add_argument('--help', help='Show this help message and exit', action='store_true') ++ parser.add_argument('-f', '--five-minute', help='Print the last five minutes of stats.', action='store_true') ++ parser.add_argument('-h', '--hour', help='Print the last hour of stats.', action='store_true') ++ parser.add_argument('-d', '--day', help='Print the last day of stats.', action='store_true') ++ parser.add_argument('-t', '--total', help='Print total stats.', action='store_true') ++ parser.add_argument('-a', '--all', help='Print all stats.', action='store_true') ++ parser.add_argument('-r', '--reset-stats', help='Reset stats after printing them.', action='store_true') ++ parser.add_argument('-s', '--sub-status', help='Print subdevice status.', action='store_true') ++ parser.add_argument('-g', '--gc', help='Invoke GC before printing status.', action='store_true') ++ args = parser.parse_args() ++ ++ if args.help: ++ parser.print_help() ++ return 0 ++ ++ if args.five_minute: ++ stats.add('five_minute') ++ if args.hour: ++ stats.add('hour') ++ if args.day: ++ stats.add('day') ++ if args.total: ++ stats.add('total') ++ if args.all: ++ stats.add('five_minute') ++ stats.add('hour') ++ stats.add('day') ++ stats.add('total') ++ if args.reset_stats: ++ reset_stats = True ++ if args.sub_status: ++ print_subdevices = True ++ if args.gc: ++ run_gc = True ++ ++ if not stats: ++ stats.add('total') ++ ++ uuid_map = map_uuid_to_device() ++ if not os.path.isdir(SYSFS_BCACHE_PATH): ++ print('bcache is not loaded.') ++ return ++ for cache in os.listdir(SYSFS_BCACHE_PATH): ++ if not os.path.isdir('%s%s' % (SYSFS_BCACHE_PATH, cache)): ++ continue ++ ++ if run_gc: ++ with open('%s%s/internal/trigger_gc' % (SYSFS_BCACHE_PATH, cache), 'w') as fd: ++ fd.write('1\n') ++ ++ dump_bcache('%s%s' % (SYSFS_BCACHE_PATH, cache), stats, print_subdevices, uuid_map.get(cache, '?')) ++ ++ if reset_stats: ++ with open('%s%s/clear_stats' % (SYSFS_BCACHE_PATH, cache), 'w') as fd: ++ fd.write('1\n') ++ ++if __name__ == '__main__': ++ main() +-- +2.26.2 + diff --git a/0017-bcache-tools-add-man-page-bcache-status.8.patch b/0017-bcache-tools-add-man-page-bcache-status.8.patch new file mode 100644 index 0000000..680e0e3 --- /dev/null +++ b/0017-bcache-tools-add-man-page-bcache-status.8.patch @@ -0,0 +1,72 @@ +From 91fd5fb518ae535e36cff1ae188d1bcef874cf40 Mon Sep 17 00:00:00 2001 +From: Coly Li +Date: Wed, 2 Sep 2020 20:09:06 +0800 +Subject: [PATCH 17/17] bcache-tools: add man page bcache-status.8 +Git-commit: 91fd5fb518ae535e36cff1ae188d1bcef874cf40 +Patch-mainline: bcache-tools-1.1 +References: jsc#SLE-9807 + +Add the initial man page for bcache-status. + +Signed-off-by: Coly Li +--- + bcache-status.8 | 47 +++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 47 insertions(+) + create mode 100644 bcache-status.8 + +diff --git a/bcache-status.8 b/bcache-status.8 +new file mode 100644 +index 0000000..f56cfb6 +--- /dev/null ++++ b/bcache-status.8 +@@ -0,0 +1,47 @@ ++.TH bcache-status 8 ++.SH NAME ++bcache-status \- Display useful bcache statistics ++ ++.SH SYNOPSIS ++.B bcache-status [ --help ] [ -f ] [ -h ] [ -d ] [ -t ] [ -a ] [ -r ] [ -s ] [ -g ] ++ ++.SH DESCRIPTION ++This command displays useful bcache statistics in a convenient way. ++ ++.SH OPTIONS ++ ++.TP ++.BR \-\-help ++Print help message and exit. ++ ++.TP ++.BR \-f ", " \-\-five\-minute ++Print the last five minutes of stats. ++ ++.TP ++.BR \-h ", " \-\-hour ++Print the last hour of stats. ++ ++.TP ++.BR \-d ", " \-\-day ++Print the last day of stats. ++ ++.TP ++.BR \-t ", " \-\-total ++Print total stats. ++ ++.TP ++.BR \-a ", " \-\-all ++Print all stats. ++ ++.TP ++.BR \-r ", " \-\-reset\-stats ++Reset stats after printing them. ++ ++.TP ++.BR \-s ", " \-\-sub\-status ++Print subdevice status. ++ ++.TP ++.BR \-g ", " \-\-gc ++Invoke GC before printing status (root only). +-- +2.26.2 + diff --git a/1001-udev-do-not-rely-on-DRIVER-variable.patch b/1001-udev-do-not-rely-on-DRIVER-variable.patch deleted file mode 100644 index 2b2f9af..0000000 --- a/1001-udev-do-not-rely-on-DRIVER-variable.patch +++ /dev/null @@ -1,39 +0,0 @@ -From b48c30983b1510d94745bd07494fa81a68a5896e Mon Sep 17 00:00:00 2001 -From: Jan Engelhardt -Date: Sat, 28 Mar 2015 10:50:57 +0100 -Subject: [PATCH] udev: do not rely on DRIVER variable - -The DRIVER variable will only be set on a single event (when the -module creates the first instance?). Any subsequent udev event, e.g. a -change event for bcache0, does not have the DRIVER tag set. In fact, -most events don't. (This can be reproduced with `udevadm trigger`.) -This leads to a change in the contents of the SYMLINK variable which -leads to removal of /dev/bcache/, since DRIVER is not set. - -Don't even bother to create such a volatile /dev/bcache/ in the -first place so users don't go chasing after it. - -References: https://bugzilla.opensuse.org/880858 ---- - 69-bcache.rules | 6 ------ - 1 file changed, 6 deletions(-) - -diff --git a/69-bcache.rules b/69-bcache.rules -index 9cc7f0d..096fde6 100644 ---- a/69-bcache.rules -+++ b/69-bcache.rules -@@ -22,11 +22,5 @@ RUN{builtin}+="kmod load bcache" - RUN+="bcache-register $tempnode" - LABEL="bcache_backing_end" - --# Cached devices: symlink --DRIVER=="bcache", ENV{CACHED_UUID}=="?*", \ -- SYMLINK+="bcache/by-uuid/$env{CACHED_UUID}" --DRIVER=="bcache", ENV{CACHED_LABEL}=="?*", \ -- SYMLINK+="bcache/by-label/$env{CACHED_LABEL}" -- - LABEL="bcache_end" - --- -2.1.4 - diff --git a/bcache-tools.changes b/bcache-tools.changes index 50e265d..1369fdc 100644 --- a/bcache-tools.changes +++ b/bcache-tools.changes @@ -1,3 +1,57 @@ +------------------------------------------------------------------- +Tue Oct 13 04:32:51 UTC 2020 - Coly Li + +- Remove dependence of smartcols bcache-tools.spec, bcache-tools + code doesn't need it now. (jsc#SLE-9807) +- Remove 1001-udev-do-not-rely-on-DRIVER-variable.patch because + we have 0013-bcache-tools-Export-CACHED_UUID-and-CACHED_LABEL.patch + to provide static UUIDs. (jsc#SLE-9807) +- bcache-tools: add man page bcache-status.8 (jsc#SLE-9807) + 0017-bcache-tools-add-man-page-bcache-status.8.patch +- bcache-tools: add bcache-status (jsc#SLE-9807) + 0016-bcache-tools-add-bcache-status.patch +- bcache-tools: make: permit only one cache device to be + specified (jsc#SLE-9807) + 0015-bcache-tools-make-permit-only-one-cache-device-to-be.patch +- bcache-tools: Remove the dependency on libsmartcols + (jsc#SLE-9807) + 0014-bcache-tools-Remove-the-dependency-on-libsmartcols.patch +- bcache-tools: Export CACHED_UUID and CACHED_LABEL + (jsc#SLE-9807) + 0013-bcache-tools-Export-CACHED_UUID-and-CACHED_LABEL.patch +- bcache-tools: Fix potential coredump issues (jsc#SLE-9807) + 0012-bcache-tools-Fix-potential-coredump-issues.patch +- bcache-tools: add print_cache_set_supported_feature_sets() + in lib.c (jsc#SLE-9807) + 0011-bcache-tools-add-print_cache_set_supported_feature_s.patch +- bcache-tools: add large_bucket incompat feature (jsc#SLE-9807) + 0010-bcache-tools-add-large_bucket-incompat-feature.patch +- bcache-tools: upgrade super block versions for feature sets + (jsc#SLE-9807) + 0009-bcache-tools-upgrade-super-block-versions-for-featur.patch +- bcache-tools: define separated super block for in-memory and + on-disk format (jsc#SLE-9807) + 0008-bcache-tools-define-separated-super-block-for-in-mem.patch +- bcache-tools: add to_cache_sb() and to_cache_sb_disk() + (jsc#SLE-9807) + 0007-bcache-tools-add-to_cache_sb-and-to_cache_sb_disk.patch +- bcache-tools: list.h: only define offsetof() when it is + undefined (jsc#SLE-9807) + 0006-bcache-tools-list.h-only-define-offsetof-when-it-is-.patch +- bcache-tools: bitwise.h: more swap bitwise for different + CPU endians (jsc#SLE-9807) + 0005-bcache-tools-bitwise.h-more-swap-bitwise-for-differe.patch +- bcache-tools: add struct cache_sb_disk into bcache.h (jsc#SLE-9807) + 0004-bcache-tools-add-struct-cache_sb_disk-into-bcache.h.patch +- bcache-tools: convert writeback to writethrough mode for zoned + backing device (jsc#SLE-9807) + 0003-bcache-tools-convert-writeback-to-writethrough-mode-.patch +- bcache-tools: add is_zoned_device() (jsc#SLE-9807) + 0002-bcache-tools-add-is_zoned_device.patch +- bcache-tools: set zoned size aligned data_offset on backing device + for zoned devive (jsc#SLE-9807) + 0001-bcache-tools-set-zoned-size-aligned-data_offset-on-b.patch + ------------------------------------------------------------------- Tue Sep 8 11:58:38 UTC 2020 - Jan Engelhardt diff --git a/bcache-tools.spec b/bcache-tools.spec index 8f77bba..441b8bc 100644 --- a/bcache-tools.spec +++ b/bcache-tools.spec @@ -25,11 +25,26 @@ Group: System/Base URL: http://bcache.evilpiepirate.org/ Source: %name-%version.tar.xz -Patch1: 1001-udev-do-not-rely-on-DRIVER-variable.patch +Patch1: 0001-bcache-tools-set-zoned-size-aligned-data_offset-on-b.patch +Patch2: 0002-bcache-tools-add-is_zoned_device.patch +Patch3: 0003-bcache-tools-convert-writeback-to-writethrough-mode-.patch +Patch4: 0004-bcache-tools-add-struct-cache_sb_disk-into-bcache.h.patch +Patch5: 0005-bcache-tools-bitwise.h-more-swap-bitwise-for-differe.patch +Patch6: 0006-bcache-tools-list.h-only-define-offsetof-when-it-is-.patch +Patch7: 0007-bcache-tools-add-to_cache_sb-and-to_cache_sb_disk.patch +Patch8: 0008-bcache-tools-define-separated-super-block-for-in-mem.patch +Patch9: 0009-bcache-tools-upgrade-super-block-versions-for-featur.patch +Patch10: 0010-bcache-tools-add-large_bucket-incompat-feature.patch +Patch11: 0011-bcache-tools-add-print_cache_set_supported_feature_s.patch +Patch12: 0012-bcache-tools-Fix-potential-coredump-issues.patch +Patch13: 0013-bcache-tools-Export-CACHED_UUID-and-CACHED_LABEL.patch +Patch14: 0014-bcache-tools-Remove-the-dependency-on-libsmartcols.patch +Patch15: 0015-bcache-tools-make-permit-only-one-cache-device-to-be.patch +Patch16: 0016-bcache-tools-add-bcache-status.patch +Patch17: 0017-bcache-tools-add-man-page-bcache-status.8.patch BuildRequires: pkg-config BuildRequires: xz BuildRequires: pkgconfig(blkid) -BuildRequires: pkgconfig(smartcols) BuildRequires: pkgconfig(uuid) %description @@ -41,8 +56,8 @@ This package contains utilities for configuring the bcache Module. %build export SUSE_ASNEEDED=0 %make_build all \ - CFLAGS="%optflags $(pkg-config blkid uuid smartcols --cflags) -std=gnu99" \ - LDFLAGS="$(pkg-config blkid uuid smartcols --libs)" + CFLAGS="%optflags $(pkg-config blkid uuid --cflags) -std=gnu99" \ + LDFLAGS="$(pkg-config blkid uuid --libs)" %install b="%buildroot"