aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorColy Li <colyli@suse.de>2021-01-01 00:16:34 +0800
committerColy Li <colyli@suse.de>2021-01-02 00:21:22 +0800
commitc0b421f3b5e4479a6f8f25b7cddf53cd240a0a7e (patch)
treeb07cab2d3be831f8a7e256180af26704551e5c9a
parent93e83d620d21411eb82fd3c4e95d7b73e79ce49d (diff)
downloadbcache-tools-c0b421f3b5e4479a6f8f25b7cddf53cd240a0a7e.tar.gz
bcache-tools: introduce BCH_FEATURE_INCOMPAT_LOG_LARGE_BUCKET_SIZE for large bucket
When large bucket feature was added, BCH_FEATURE_INCOMPAT_LARGE_BUCKET was introduced into incompat feature set. It indicates bucket_size_hi is added at the tail of struct cache_sb_disk, to extend current 16bit bucket size to 32bit with existing bucket_size in struct cache_sb_disk. This is not a good idea, there are two obvious problems, - Bucket size is always value power of 2, if store log2(bucket size) in existing bucket_size of struct cache_sb_disk, it is unnecessary to add bucket_size_hi. - Macro csum_set() assumes d[SB_JOURNAL_BUCKETS] is the last member in struct cache_sb_disk, bucket_size_hi was added after d[] which makes csum_set calculate an unexpected super block checksum. To fix the above problems, this patch introduces a new incompat feature bit BCH_FEATURE_INCOMPAT_LOG_LARGE_BUCKET_SIZE, when this bit is set, it means bucket_size in struct cache_sb_disk stores the order of power of 2 bucket size value. When user specifies a bucket size larger than 32768 sectors, BCH_FEATURE_INCOMPAT_LOG_LARGE_BUCKET_SIZE will be set to incompat feature set, and bucket_size stores log2(bucket size) more than store the real bucket size value. The obsoleted BCH_FEATURE_INCOMPAT_LARGE_BUCKET won't be used anymore, bcache-tools only display "obso_large_bucket" for cache device created with BCH_FEATURE_INCOMPAT_LARGE_BUCKET, kernel driver will make bcache device as read-only if BCH_FEATURE_INCOMPAT_LARGE_BUCKET is set. With this change, the unnecessary extra space extend of bcache on-disk super block can be avoided, and csum_set() may generate expected check sum as well. Fixes: 8c063851990a ("bcache-tools: add large_bucket incompat feature") Signed-off-by: Coly Li <colyli@suse.de>
-rw-r--r--bcache.h13
-rw-r--r--features.c4
-rw-r--r--lib.c17
-rw-r--r--lib.h2
4 files changed, 28 insertions, 8 deletions
diff --git a/bcache.h b/bcache.h
index 58e973c7..6dcdbb7a 100644
--- a/bcache.h
+++ b/bcache.h
@@ -100,7 +100,7 @@ struct cache_sb_disk {
__le16 keys;
};
__le64 d[SB_JOURNAL_BUCKETS]; /* journal buckets */
- __le16 bucket_size_hi;
+ __le16 obso_bucket_size_hi; /* obsoleted */
};
/*
@@ -202,7 +202,8 @@ uint64_t crc64(const void *data, size_t len);
#define BCH_FEATURE_COMPAT_SUPP 0
#define BCH_FEATURE_RO_COMPAT_SUPP 0
-#define BCH_FEATURE_INCOMPAT_SUPP BCH_FEATURE_INCOMPAT_LARGE_BUCKET
+#define BCH_FEATURE_INCOMPAT_SUPP (BCH_FEATURE_INCOMPAT_OBSO_LARGE_BUCKET| \
+ BCH_FEATURE_INCOMPAT_LOG_LARGE_BUCKET_SIZE)
#define BCH_HAS_COMPAT_FEATURE(sb, mask) \
((sb)->feature_compat & (mask))
@@ -214,7 +215,10 @@ uint64_t crc64(const void *data, size_t len);
/* Feature set definition */
/* Incompat feature set */
-#define BCH_FEATURE_INCOMPAT_LARGE_BUCKET 0x0001 /* 32bit bucket size */
+/* 32bit bucket size, obsoleted */
+#define BCH_FEATURE_INCOMPAT_OBSO_LARGE_BUCKET 0x0001
+/* real bucket size is (1 << bucket_size) */
+#define BCH_FEATURE_INCOMPAT_LOG_LARGE_BUCKET_SIZE 0x0002
#define BCH_FEATURE_COMPAT_FUNCS(name, flagname) \
static inline int bch_has_feature_##name(struct cache_sb *sb) \
@@ -267,6 +271,7 @@ static inline void bch_clear_feature_##name(struct cache_sb *sb) \
~BCH##_FEATURE_INCOMPAT_##flagname; \
}
-BCH_FEATURE_INCOMPAT_FUNCS(large_bucket, LARGE_BUCKET);
+BCH_FEATURE_INCOMPAT_FUNCS(obso_large_bucket, OBSO_LARGE_BUCKET);
+BCH_FEATURE_INCOMPAT_FUNCS(large_bucket, LOG_LARGE_BUCKET_SIZE);
#endif
diff --git a/features.c b/features.c
index 181e348c..f7f62244 100644
--- a/features.c
+++ b/features.c
@@ -20,7 +20,9 @@ struct feature {
};
static struct feature feature_list[] = {
- {BCH_FEATURE_INCOMPAT, BCH_FEATURE_INCOMPAT_LARGE_BUCKET,
+ {BCH_FEATURE_INCOMPAT, BCH_FEATURE_INCOMPAT_OBSO_LARGE_BUCKET,
+ "obso_large_bucket"},
+ {BCH_FEATURE_INCOMPAT, BCH_FEATURE_INCOMPAT_LOG_LARGE_BUCKET_SIZE,
"large_bucket"},
{0, 0, 0 },
};
diff --git a/lib.c b/lib.c
index a529ad3e..8e7da8be 100644
--- a/lib.c
+++ b/lib.c
@@ -21,6 +21,19 @@
* utils function
*/
+static unsigned int log2_u32(uint32_t n)
+{
+ int r = 0;
+
+ n = n >> 1;
+ while (n) {
+ n = n >> 1;
+ r++;
+ }
+
+ return r;
+}
+
static void trim_prefix(char *dest, char *src, int num)
{
strcpy(dest, src + num);
@@ -772,7 +785,7 @@ struct cache_sb *to_cache_sb(struct cache_sb *sb,
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;
+ sb->bucket_size = 1 << le16_to_cpu(sb_disk->bucket_size);
return sb;
}
@@ -824,7 +837,7 @@ struct cache_sb_disk *to_cache_sb_disk(struct cache_sb_disk *sb_disk,
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);
+ sb_disk->bucket_size = cpu_to_le16(log2_u32(sb->bucket_size));
return sb_disk;
}
diff --git a/lib.h b/lib.h
index 9b5ed024..0357a11a 100644
--- a/lib.h
+++ b/lib.h
@@ -13,7 +13,7 @@ struct dev {
char label[SB_LABEL_SIZE + 1];
char uuid[40];
uint16_t sectors_per_block;
- uint16_t sectors_per_bucket;
+ uint32_t sectors_per_bucket;
char cset[40];
char state[40];
char bname[40];