Skip to content

Commit b16671e

Browse files
Coly Liaxboe
authored andcommitted
bcache: 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 the incompat feature set. It used bucket_size_hi (which was 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, it is renamed to BCH_FEATURE_INCOMPAT_OBSO_LARGE_BUCKET and still only recognized by kernel driver for legacy compatible purpose. The previous bucket_size_hi is renmaed to obso_bucket_size_hi in struct cache_sb_disk and not used in bcache-tools anymore. For cache device created with BCH_FEATURE_INCOMPAT_LARGE_BUCKET feature, bcache-tools and kernel driver still recognize the feature string and display it as "obso_large_bucket". 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: ffa4703 ("bcache: add bucket_size_hi into struct cache_sb_disk for large bucket") Signed-off-by: Coly Li <colyli@suse.de> Cc: stable@vger.kernel.org # 5.9+ Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 1dfc068 commit b16671e

File tree

4 files changed

+29
-8
lines changed

4 files changed

+29
-8
lines changed

drivers/md/bcache/features.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ struct feature {
1717
};
1818

1919
static struct feature feature_list[] = {
20-
{BCH_FEATURE_INCOMPAT, BCH_FEATURE_INCOMPAT_LARGE_BUCKET,
20+
{BCH_FEATURE_INCOMPAT, BCH_FEATURE_INCOMPAT_LOG_LARGE_BUCKET_SIZE,
2121
"large_bucket"},
2222
{0, 0, 0 },
2323
};

drivers/md/bcache/features.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,15 @@
1313

1414
/* Feature set definition */
1515
/* Incompat feature set */
16-
#define BCH_FEATURE_INCOMPAT_LARGE_BUCKET 0x0001 /* 32bit bucket size */
16+
/* 32bit bucket size, obsoleted */
17+
#define BCH_FEATURE_INCOMPAT_OBSO_LARGE_BUCKET 0x0001
18+
/* real bucket size is (1 << bucket_size) */
19+
#define BCH_FEATURE_INCOMPAT_LOG_LARGE_BUCKET_SIZE 0x0002
1720

1821
#define BCH_FEATURE_COMPAT_SUPP 0
1922
#define BCH_FEATURE_RO_COMPAT_SUPP 0
20-
#define BCH_FEATURE_INCOMPAT_SUPP BCH_FEATURE_INCOMPAT_LARGE_BUCKET
23+
#define BCH_FEATURE_INCOMPAT_SUPP (BCH_FEATURE_INCOMPAT_OBSO_LARGE_BUCKET| \
24+
BCH_FEATURE_INCOMPAT_LOG_LARGE_BUCKET_SIZE)
2125

2226
#define BCH_HAS_COMPAT_FEATURE(sb, mask) \
2327
((sb)->feature_compat & (mask))
@@ -77,7 +81,8 @@ static inline void bch_clear_feature_##name(struct cache_sb *sb) \
7781
~BCH##_FEATURE_INCOMPAT_##flagname; \
7882
}
7983

80-
BCH_FEATURE_INCOMPAT_FUNCS(large_bucket, LARGE_BUCKET);
84+
BCH_FEATURE_INCOMPAT_FUNCS(obso_large_bucket, OBSO_LARGE_BUCKET);
85+
BCH_FEATURE_INCOMPAT_FUNCS(large_bucket, LOG_LARGE_BUCKET_SIZE);
8186

8287
static inline bool bch_has_unknown_compat_features(struct cache_sb *sb)
8388
{

drivers/md/bcache/super.c

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,25 @@ static unsigned int get_bucket_size(struct cache_sb *sb, struct cache_sb_disk *s
6464
{
6565
unsigned int bucket_size = le16_to_cpu(s->bucket_size);
6666

67-
if (sb->version >= BCACHE_SB_VERSION_CDEV_WITH_FEATURES &&
68-
bch_has_feature_large_bucket(sb))
69-
bucket_size |= le16_to_cpu(s->bucket_size_hi) << 16;
67+
if (sb->version >= BCACHE_SB_VERSION_CDEV_WITH_FEATURES) {
68+
if (bch_has_feature_large_bucket(sb)) {
69+
unsigned int max, order;
70+
71+
max = sizeof(unsigned int) * BITS_PER_BYTE - 1;
72+
order = le16_to_cpu(s->bucket_size);
73+
/*
74+
* bcache tool will make sure the overflow won't
75+
* happen, an error message here is enough.
76+
*/
77+
if (order > max)
78+
pr_err("Bucket size (1 << %u) overflows\n",
79+
order);
80+
bucket_size = 1 << order;
81+
} else if (bch_has_feature_obso_large_bucket(sb)) {
82+
bucket_size +=
83+
le16_to_cpu(s->obso_bucket_size_hi) << 16;
84+
}
85+
}
7086

7187
return bucket_size;
7288
}

include/uapi/linux/bcache.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ struct cache_sb_disk {
213213
__le16 keys;
214214
};
215215
__le64 d[SB_JOURNAL_BUCKETS]; /* journal buckets */
216-
__le16 bucket_size_hi;
216+
__le16 obso_bucket_size_hi; /* obsoleted */
217217
};
218218

219219
/*

0 commit comments

Comments
 (0)