aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorColy Li <colyli@suse.de>2020-08-17 01:37:17 +0800
committerColy Li <colyli@suse.de>2020-08-17 20:02:42 +0800
commit8c063851990a5e82ba1727907994a46201d9e842 (patch)
treed12349cbb97ac357b25788b3bcd2904941cf8790
parent5e7bd462ee91793708d6f0c34c46fb904bee7efb (diff)
downloadbcache-tools-8c063851990a5e82ba1727907994a46201d9e842.tar.gz
bcache-tools: add large_bucket incompat feature
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 <colyli@suse.de>
-rw-r--r--bcache.h8
-rw-r--r--features.c2
-rw-r--r--lib.c19
-rw-r--r--lib.h1
-rw-r--r--make.c18
5 files changed, 42 insertions, 6 deletions
diff --git a/bcache.h b/bcache.h
index 9d969e12..6aef9c47 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 a1c9884d..df15862e 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 dcf752c1..efabeb14 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>
@@ -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 b37608e3..1dd2bfed 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 a2390233..9631857c 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':