Skip to content

Commit 7777fef

Browse files
taoddintel-lab-lkp
authored andcommitted
bcache: consider the fragmentation when update the writeback rate
Current way to calculate the writeback rate only considered the dirty sectors, this usually works fine when the fragmentation is not high, but it will give us unreasonable small rate when we are under a situation that very few dirty sectors consumed a lot dirty buckets. In some case, the dirty bucekts can reached to CUTOFF_WRITEBACK_SYNC while the dirty data(sectors) noteven reached the writeback_percent, the writeback rate will still be the minimum value (4k), thus it will cause all the writes to be stucked in a non-writeback mode because of the slow writeback. We accelerate the rate in 3 stages with different aggressiveness, the first stage starts when dirty buckets percent reach above BCH_WRITEBACK_FRAGMENT_THRESHOLD_LOW (50), the second is BCH_WRITEBACK_FRAGMENT_THRESHOLD_MID (57), the third is BCH_WRITEBACK_FRAGMENT_THRESHOLD_HIGH (64). By default the first stage tries to writeback the amount of dirty data in one bucket (on average) in (1 / (dirty_buckets_percent - 50)) second, the second stage tries to writeback the amount of dirty data in one bucket in (1 / (dirty_buckets_percent - 57)) * 200 millisecond, the third stage tries to writeback the amount of dirty data in one bucket in (1 / (dirty_buckets_percent - 64)) * 20 millisecond. Signed-off-by: dongdong tao <dongdong.tao@canonical.com>
1 parent e71ba94 commit 7777fef

File tree

4 files changed

+64
-0
lines changed

4 files changed

+64
-0
lines changed

drivers/md/bcache/bcache.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,9 @@ struct cached_dev {
385385
unsigned int writeback_rate_update_seconds;
386386
unsigned int writeback_rate_i_term_inverse;
387387
unsigned int writeback_rate_p_term_inverse;
388+
unsigned int writeback_rate_fp_term_low;
389+
unsigned int writeback_rate_fp_term_mid;
390+
unsigned int writeback_rate_fp_term_high;
388391
unsigned int writeback_rate_minimum;
389392

390393
enum stop_on_failure stop_when_cache_set_failed;

drivers/md/bcache/sysfs.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ rw_attribute(writeback_rate);
121121
rw_attribute(writeback_rate_update_seconds);
122122
rw_attribute(writeback_rate_i_term_inverse);
123123
rw_attribute(writeback_rate_p_term_inverse);
124+
rw_attribute(writeback_rate_fp_term_low);
125+
rw_attribute(writeback_rate_fp_term_mid);
126+
rw_attribute(writeback_rate_fp_term_high);
124127
rw_attribute(writeback_rate_minimum);
125128
read_attribute(writeback_rate_debug);
126129

@@ -205,6 +208,9 @@ SHOW(__bch_cached_dev)
205208
var_print(writeback_rate_update_seconds);
206209
var_print(writeback_rate_i_term_inverse);
207210
var_print(writeback_rate_p_term_inverse);
211+
var_print(writeback_rate_fp_term_low);
212+
var_print(writeback_rate_fp_term_mid);
213+
var_print(writeback_rate_fp_term_high);
208214
var_print(writeback_rate_minimum);
209215

210216
if (attr == &sysfs_writeback_rate_debug) {
@@ -331,6 +337,15 @@ STORE(__cached_dev)
331337
sysfs_strtoul_clamp(writeback_rate_p_term_inverse,
332338
dc->writeback_rate_p_term_inverse,
333339
1, UINT_MAX);
340+
sysfs_strtoul_clamp(writeback_rate_fp_term_low,
341+
dc->writeback_rate_fp_term_low,
342+
1, UINT_MAX);
343+
sysfs_strtoul_clamp(writeback_rate_fp_term_mid,
344+
dc->writeback_rate_fp_term_mid,
345+
1, UINT_MAX);
346+
sysfs_strtoul_clamp(writeback_rate_fp_term_high,
347+
dc->writeback_rate_fp_term_high,
348+
1, UINT_MAX);
334349
sysfs_strtoul_clamp(writeback_rate_minimum,
335350
dc->writeback_rate_minimum,
336351
1, UINT_MAX);
@@ -502,6 +517,9 @@ static struct attribute *bch_cached_dev_files[] = {
502517
&sysfs_writeback_rate_update_seconds,
503518
&sysfs_writeback_rate_i_term_inverse,
504519
&sysfs_writeback_rate_p_term_inverse,
520+
&sysfs_writeback_rate_fp_term_low,
521+
&sysfs_writeback_rate_fp_term_mid,
522+
&sysfs_writeback_rate_fp_term_high,
505523
&sysfs_writeback_rate_minimum,
506524
&sysfs_writeback_rate_debug,
507525
&sysfs_io_errors,

drivers/md/bcache/writeback.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,42 @@ static void __update_writeback_rate(struct cached_dev *dc)
8888
int64_t integral_scaled;
8989
uint32_t new_rate;
9090

91+
/*
92+
* We need to consider the number of dirty buckets as well
93+
* when calculating the proportional_scaled, Otherwise we might
94+
* have an unreasonable small writeback rate at a highly fragmented situation
95+
* when very few dirty sectors consumed a lot dirty buckets, the
96+
* worst case is when dirty_data reached writeback_percent and
97+
* dirty buckets reached to cutoff_writeback_sync, but the rate
98+
* still will be at the minimum value, which will cause the write
99+
* stuck at a non-writeback mode.
100+
*/
101+
struct cache_set *c = dc->disk.c;
102+
103+
int64_t dirty_buckets = c->nbuckets - c->avail_nbuckets;
104+
105+
if (c->gc_stats.in_use > BCH_WRITEBACK_FRAGMENT_THRESHOLD_LOW && dirty > 0) {
106+
int64_t fragment = (dirty_buckets * c->cache->sb.bucket_size) / dirty;
107+
int64_t fp_term;
108+
int64_t fps;
109+
110+
if (c->gc_stats.in_use <= BCH_WRITEBACK_FRAGMENT_THRESHOLD_MID) {
111+
fp_term = dc->writeback_rate_fp_term_low *
112+
(c->gc_stats.in_use - BCH_WRITEBACK_FRAGMENT_THRESHOLD_LOW);
113+
} else if (c->gc_stats.in_use <= BCH_WRITEBACK_FRAGMENT_THRESHOLD_HIGH) {
114+
fp_term = dc->writeback_rate_fp_term_mid *
115+
(c->gc_stats.in_use - BCH_WRITEBACK_FRAGMENT_THRESHOLD_MID);
116+
} else {
117+
fp_term = dc->writeback_rate_fp_term_high *
118+
(c->gc_stats.in_use - BCH_WRITEBACK_FRAGMENT_THRESHOLD_HIGH);
119+
}
120+
fps = (dirty / dirty_buckets) * fp_term;
121+
if (fragment > 3 && fps > proportional_scaled) {
122+
//Only overrite the p when fragment > 3
123+
proportional_scaled = fps;
124+
}
125+
}
126+
91127
if ((error < 0 && dc->writeback_rate_integral > 0) ||
92128
(error > 0 && time_before64(local_clock(),
93129
dc->writeback_rate.next + NSEC_PER_MSEC))) {
@@ -984,6 +1020,9 @@ void bch_cached_dev_writeback_init(struct cached_dev *dc)
9841020

9851021
dc->writeback_rate_update_seconds = WRITEBACK_RATE_UPDATE_SECS_DEFAULT;
9861022
dc->writeback_rate_p_term_inverse = 40;
1023+
dc->writeback_rate_fp_term_low = 1;
1024+
dc->writeback_rate_fp_term_mid = 5;
1025+
dc->writeback_rate_fp_term_high = 50;
9871026
dc->writeback_rate_i_term_inverse = 10000;
9881027

9891028
WARN_ON(test_and_clear_bit(BCACHE_DEV_WB_RUNNING, &dc->disk.flags));

drivers/md/bcache/writeback.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616

1717
#define BCH_AUTO_GC_DIRTY_THRESHOLD 50
1818

19+
#define BCH_WRITEBACK_FRAGMENT_THRESHOLD_LOW 50
20+
#define BCH_WRITEBACK_FRAGMENT_THRESHOLD_MID 57
21+
#define BCH_WRITEBACK_FRAGMENT_THRESHOLD_HIGH 64
22+
1923
#define BCH_DIRTY_INIT_THRD_MAX 64
2024
/*
2125
* 14 (16384ths) is chosen here as something that each backing device

0 commit comments

Comments
 (0)