diff options
author | Coly Li <colyli@suse.de> | 2018-12-20 22:54:00 +0800 |
---|---|---|
committer | Coly Li <colyli@suse.de> | 2018-12-20 22:54:00 +0800 |
commit | 42f313fef4a5cfcdc959024516ed268fa7d27f3f (patch) | |
tree | e4d102ae3df7ffd744ab924aed64dec2606249e0 | |
parent | 17469c1fd4fab223b212497f60e29d08455ac006 (diff) | |
download | bcache-patches-42f313fef4a5cfcdc959024516ed268fa7d27f3f.tar.gz |
for-next: add sysfs fixes
14 files changed, 653 insertions, 0 deletions
diff --git a/for-next/0001-bcache-not-use-hard-coded-memset-size-in-bch_cache_a.patch b/for-next/0001-bcache-not-use-hard-coded-memset-size-in-bch_cache_a.patch new file mode 100644 index 0000000..fe3ad5c --- /dev/null +++ b/for-next/0001-bcache-not-use-hard-coded-memset-size-in-bch_cache_a.patch @@ -0,0 +1,36 @@ +From 953e7c069208c947817de96c29e4444ebac62dcc Mon Sep 17 00:00:00 2001 +From: Coly Li <colyli@suse.de> +Date: Thu, 20 Dec 2018 14:10:08 +0800 +Subject: [PATCH] bcache: not use hard coded memset size in + bch_cache_accounting_clear() + +In stats.c:bch_cache_accounting_clear(), a hard coded number '7' is +used in memset(). It is because in struct cache_stats, there are 7 +atomic_t type members. This is not good when new members added into +struct stats, the hard coded number will only clear part of memory. + +This patch replaces 'sizeof(unsigned long) * 7' by more generic +'sizeof(struct cache_stats))', to avoid potential error if new +member added into struct cache_stats. + +Signed-off-by: Coly Li <colyli@suse.de> +--- + drivers/md/bcache/stats.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/md/bcache/stats.c b/drivers/md/bcache/stats.c +index 894410f3f829..ba1c93791d8d 100644 +--- a/drivers/md/bcache/stats.c ++++ b/drivers/md/bcache/stats.c +@@ -111,7 +111,7 @@ void bch_cache_accounting_clear(struct cache_accounting *acc) + { + memset(&acc->total.cache_hits, + 0, +- sizeof(unsigned long) * 7); ++ sizeof(struct cache_stats)); + } + + void bch_cache_accounting_destroy(struct cache_accounting *acc) +-- +2.16.4 + diff --git a/for-next/sysfs-fix/0000-cover-letter.patch b/for-next/sysfs-fix/0000-cover-letter.patch new file mode 100644 index 0000000..061edec --- /dev/null +++ b/for-next/sysfs-fix/0000-cover-letter.patch @@ -0,0 +1,34 @@ +From 3eb7a1339e1f928f91c6479523daf5bea97c66b0 Mon Sep 17 00:00:00 2001 +From: Coly Li <colyli@suse.de> +Date: Thu, 20 Dec 2018 22:47:56 +0800 +Subject: [PATCH 00/11] fixes for setting values via sysfs interface + +When setting bcache parameters via sysfs interface, current code has +potential overflow and results unexpected value got set. Once such +condition happens, it is very hard to find out in product environment. + +This patch set is an effort to fix such overflow, to avoid further +unpected problems. + +Coly Li +--- +Coly Li (11): + bcache: fix input integer overflow of congested threshold + bcache: fix input overflow to sequential_cutoff + bcache: add sysfs_strtoul_bool() for setting bit-field variables + bcache: use sysfs_strtoul_bool() to set bit-field variables + bcache: fix input overflow to writeback_delay + bcache: fix potential div-zero error of writeback_rate_i_term_inverse + bcache: fix potential div-zero error of writeback_rate_p_term_inverse + bcache: fix input overflow to writeback_rate_minimum + bcache: fix input overflow to journal_delay_ms + bcache: fix input overflow to cache set io_error_limit + bcache: fix input overflow to cache set sysfs file io_error_halflife + + drivers/md/bcache/sysfs.c | 61 ++++++++++++++++++++++++++++++----------------- + drivers/md/bcache/sysfs.h | 10 ++++++++ + 2 files changed, 49 insertions(+), 22 deletions(-) + +-- +2.16.4 + diff --git a/for-next/sysfs-fix/0001-bcache-fix-input-integer-overflow-of-congested-thres.patch b/for-next/sysfs-fix/0001-bcache-fix-input-integer-overflow-of-congested-thres.patch new file mode 100644 index 0000000..73a61a7 --- /dev/null +++ b/for-next/sysfs-fix/0001-bcache-fix-input-integer-overflow-of-congested-thres.patch @@ -0,0 +1,46 @@ +From 1812ee89e1469fb27e3eb175632c74d88e9695cd Mon Sep 17 00:00:00 2001 +From: Coly Li <colyli@suse.de> +Date: Thu, 20 Dec 2018 14:54:07 +0800 +Subject: [PATCH 01/11] bcache: fix input integer overflow of congested + threshold + +Cache set congested threshold values congested_read_threshold_us and +congested_write_threshold_us can be set via sysfs interface. These +two values are 'unsigned int' type, but sysfs interface uses strtoul +to convert input string. So if people input a large number like +9999999999, the value indeed set is 1410065407, which is not expected +behavior. + +This patch replaces sysfs_strtoul() by sysfs_strtoul_clamp() when +convert input string to unsigned int value, and set value range in +[0, UINT_MAX], to avoid the above integer overflow errors. + +Signed-off-by: Coly Li <colyli@suse.de> +--- + drivers/md/bcache/sysfs.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c +index b5028ba90795..b7cbfeb63007 100644 +--- a/drivers/md/bcache/sysfs.c ++++ b/drivers/md/bcache/sysfs.c +@@ -766,10 +766,12 @@ STORE(__bch_cache_set) + c->shrink.scan_objects(&c->shrink, &sc); + } + +- sysfs_strtoul(congested_read_threshold_us, +- c->congested_read_threshold_us); +- sysfs_strtoul(congested_write_threshold_us, +- c->congested_write_threshold_us); ++ sysfs_strtoul_clamp(congested_read_threshold_us, ++ c->congested_read_threshold_us, ++ 0, UINT_MAX); ++ sysfs_strtoul_clamp(congested_write_threshold_us, ++ c->congested_write_threshold_us, ++ 0, UINT_MAX); + + if (attr == &sysfs_errors) { + v = __sysfs_match_string(error_actions, -1, buf); +-- +2.16.4 + diff --git a/for-next/sysfs-fix/0002-bcache-fix-input-overflow-to-sequential_cutoff.patch b/for-next/sysfs-fix/0002-bcache-fix-input-overflow-to-sequential_cutoff.patch new file mode 100644 index 0000000..565610c --- /dev/null +++ b/for-next/sysfs-fix/0002-bcache-fix-input-overflow-to-sequential_cutoff.patch @@ -0,0 +1,38 @@ +From acae57d8aec19bd6425f461d3232ca38b0ff0273 Mon Sep 17 00:00:00 2001 +From: Coly Li <colyli@suse.de> +Date: Thu, 20 Dec 2018 15:17:47 +0800 +Subject: [PATCH 02/11] bcache: fix input overflow to sequential_cutoff + +People may set sequential_cutoff of a cached device via sysfs file, +but current code does not check input value overflow. E.g. if value +4294967295 (UINT_MAX) is written to file sequential_cutoff, its value +is 4GB, but if 4294967296 (UINT_MAX + 1) is written into, its value +will be 0. This is an unexpected behavior. + +This patch replaces d_strtoi_h() by sysfs_strtoul_clamp() to convert +input string to unsigned integer value, and limit its range in +[0, UINT_MAX]. Then the input overflow can be fixed. + +Signed-off-by: Coly Li <colyli@suse.de> +--- + drivers/md/bcache/sysfs.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c +index b7cbfeb63007..29564bcb76c3 100644 +--- a/drivers/md/bcache/sysfs.c ++++ b/drivers/md/bcache/sysfs.c +@@ -310,7 +310,9 @@ STORE(__cached_dev) + dc->io_disable = v ? 1 : 0; + } + +- d_strtoi_h(sequential_cutoff); ++ sysfs_strtoul_clamp(sequential_cutoff, ++ dc->sequential_cutoff, ++ 0, UINT_MAX); + d_strtoi_h(readahead); + + if (attr == &sysfs_clear_stats) +-- +2.16.4 + diff --git a/for-next/sysfs-fix/0003-bcache-add-sysfs_strtoul_bool-for-setting-bit-field-.patch b/for-next/sysfs-fix/0003-bcache-add-sysfs_strtoul_bool-for-setting-bit-field-.patch new file mode 100644 index 0000000..0c01911 --- /dev/null +++ b/for-next/sysfs-fix/0003-bcache-add-sysfs_strtoul_bool-for-setting-bit-field-.patch @@ -0,0 +1,51 @@ +From f72811bd939f2bdd407b0896d4d34573d48bf5c6 Mon Sep 17 00:00:00 2001 +From: Coly Li <colyli@suse.de> +Date: Thu, 20 Dec 2018 16:54:50 +0800 +Subject: [PATCH 03/11] bcache: add sysfs_strtoul_bool() for setting bit-field + variables + +When setting bool values via sysfs interface, e.g. writeback_metadata, +if writting 1 into writeback_metadata file, dc->writeback_metadata is +set to 1, but if writting 2 into the file, dc->writeback_metadata is +0. This is misleading, a better result should be 1 for all non-zero +input value. + +It is because dc->writeback_metadata is a bit-field variable, and +current code simply use d_strtoul() to convert a string into integer +and takes the lowest bit value. To fix such error, we need a routine +to convert the input string into unsigned integer, and set target +variable to 1 if the converted integer is non-zero. + +This patch introduces a new macro called sysfs_strtoul_bool(), it can +be used to convert input string into bool value, we can use it to set +bool value for bit-field vairables. + +Signed-off-by: Coly Li <colyli@suse.de> +--- + drivers/md/bcache/sysfs.h | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/md/bcache/sysfs.h b/drivers/md/bcache/sysfs.h +index 3fe82425859c..262c83bac2be 100644 +--- a/drivers/md/bcache/sysfs.h ++++ b/drivers/md/bcache/sysfs.h +@@ -79,6 +79,16 @@ do { \ + return strtoul_safe(buf, var) ?: (ssize_t) size; \ + } while (0) + ++#define sysfs_strtoul_bool(file, var) \ ++do { \ ++ if (attr == &sysfs_## file) { \ ++ int v = strtoul_or_return(buf); \ ++ \ ++ (var) = v ? 1 : 0; \ ++ return 0; \ ++ } \ ++} while (0) ++ + #define sysfs_strtoul_clamp(file, var, min, max) \ + do { \ + if (attr == &sysfs_ ## file) \ +-- +2.16.4 + diff --git a/for-next/sysfs-fix/0004-bcache-use-sysfs_strtoul_bool-to-set-bit-field-varia.patch b/for-next/sysfs-fix/0004-bcache-use-sysfs_strtoul_bool-to-set-bit-field-varia.patch new file mode 100644 index 0000000..56fa1ee --- /dev/null +++ b/for-next/sysfs-fix/0004-bcache-use-sysfs_strtoul_bool-to-set-bit-field-varia.patch @@ -0,0 +1,72 @@ +From 01964349722aaedb3b735651057f9e1d2d056c98 Mon Sep 17 00:00:00 2001 +From: Coly Li <colyli@suse.de> +Date: Thu, 20 Dec 2018 17:40:45 +0800 +Subject: [PATCH 04/11] bcache: use sysfs_strtoul_bool() to set bit-field + variables + +When setting bcache parameters via sysfs, there are some variables are +defined as bit-field value. Current bcache code in sysfs.c uses either +d_strtoul() or sysfs_strtoul() to convert the input string to unsigned +integer value and set it to the corresponded bit-field value. + +The problem is, the bit-field value only takes the lowest bit of the +converted value. If input is 2, the expected value (like bool value) +of the bit-field value should be 1, but indeed it is 0. + +The following sysfs files for bit-field variables have such problem, + bypass_torture_test, for dc->bypass_torture_test + writeback_metadata, for dc->writeback_metadata + writeback_running, for dc->writeback_running + verify, for c->verify + key_merging_disabled, for c->key_merging_disabled + gc_always_rewrite, for c->gc_always_rewrite + btree_shrinker_disabled,for c->shrinker_disabled + copy_gc_enabled, for c->copy_gc_enabled + +This patch uses sysfs_strtoul_bool() to set such bit-field variables, +then if the converted value is non-zero, the bit-field variables will +be set to 1, like setting a bool value like expensive_debug_checks. + +Signed-off-by: Coly Li <colyli@suse.de> +--- + drivers/md/bcache/sysfs.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c +index 29564bcb76c3..0753568631e5 100644 +--- a/drivers/md/bcache/sysfs.c ++++ b/drivers/md/bcache/sysfs.c +@@ -274,9 +274,9 @@ STORE(__cached_dev) + + sysfs_strtoul(data_csum, dc->disk.data_csum); + d_strtoul(verify); +- d_strtoul(bypass_torture_test); +- d_strtoul(writeback_metadata); +- d_strtoul(writeback_running); ++ sysfs_strtoul_bool(bypass_torture_test, dc->bypass_torture_test); ++ sysfs_strtoul_bool(writeback_metadata, dc->writeback_metadata); ++ sysfs_strtoul_bool(writeback_running, dc->writeback_running); + d_strtoul(writeback_delay); + + sysfs_strtoul_clamp(writeback_percent, dc->writeback_percent, 0, 40); +@@ -804,12 +804,12 @@ STORE(__bch_cache_set) + } + + sysfs_strtoul(journal_delay_ms, c->journal_delay_ms); +- sysfs_strtoul(verify, c->verify); +- sysfs_strtoul(key_merging_disabled, c->key_merging_disabled); ++ sysfs_strtoul_bool(verify, c->verify); ++ sysfs_strtoul_bool(key_merging_disabled,c->key_merging_disabled); + sysfs_strtoul(expensive_debug_checks, c->expensive_debug_checks); +- sysfs_strtoul(gc_always_rewrite, c->gc_always_rewrite); +- sysfs_strtoul(btree_shrinker_disabled, c->shrinker_disabled); +- sysfs_strtoul(copy_gc_enabled, c->copy_gc_enabled); ++ sysfs_strtoul_bool(gc_always_rewrite, c->gc_always_rewrite); ++ sysfs_strtoul_bool(btree_shrinker_disabled, c->shrinker_disabled); ++ sysfs_strtoul_bool(copy_gc_enabled, c->copy_gc_enabled); + + return size; + } +-- +2.16.4 + diff --git a/for-next/sysfs-fix/0005-bcache-fix-input-overflow-to-writeback_delay.patch b/for-next/sysfs-fix/0005-bcache-fix-input-overflow-to-writeback_delay.patch new file mode 100644 index 0000000..a4e1677 --- /dev/null +++ b/for-next/sysfs-fix/0005-bcache-fix-input-overflow-to-writeback_delay.patch @@ -0,0 +1,36 @@ +From 58bbf30cc1eb290cfe753d9472a72f66e3f46088 Mon Sep 17 00:00:00 2001 +From: Coly Li <colyli@suse.de> +Date: Thu, 20 Dec 2018 18:02:07 +0800 +Subject: [PATCH 05/11] bcache: fix input overflow to writeback_delay + +Sysfs file writeback_delay is used to configure dc->writeback_delay +which is type unsigned int. But bcache code uses sysfs_strtoul() to +convert the input string, therefore it might be overflowed if the input +value is too large. E.g. input value is 4294967296 but indeed 0 is +set to dc->writeback_delay. + +This patch uses sysfs_strtoul_clamp() to convert the input string and +set the result value range in [0, UINT_MAX] to avoid such unsigned +integer overflow. + +Signed-off-by: Coly Li <colyli@suse.de> +--- + drivers/md/bcache/sysfs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c +index 0753568631e5..6a1774a6c5fa 100644 +--- a/drivers/md/bcache/sysfs.c ++++ b/drivers/md/bcache/sysfs.c +@@ -277,7 +277,7 @@ STORE(__cached_dev) + sysfs_strtoul_bool(bypass_torture_test, dc->bypass_torture_test); + sysfs_strtoul_bool(writeback_metadata, dc->writeback_metadata); + sysfs_strtoul_bool(writeback_running, dc->writeback_running); +- d_strtoul(writeback_delay); ++ sysfs_strtoul_clamp(writeback_delay, dc->writeback_delay, 0, UINT_MAX); + + sysfs_strtoul_clamp(writeback_percent, dc->writeback_percent, 0, 40); + +-- +2.16.4 + diff --git a/for-next/sysfs-fix/0006-bcache-fix-potential-div-zero-error-of-writeback_rat.patch b/for-next/sysfs-fix/0006-bcache-fix-potential-div-zero-error-of-writeback_rat.patch new file mode 100644 index 0000000..e200a52 --- /dev/null +++ b/for-next/sysfs-fix/0006-bcache-fix-potential-div-zero-error-of-writeback_rat.patch @@ -0,0 +1,47 @@ +From ab113e3198a119722703d9ddc4b1398d05a44d34 Mon Sep 17 00:00:00 2001 +From: Coly Li <colyli@suse.de> +Date: Thu, 20 Dec 2018 20:33:43 +0800 +Subject: [PATCH 06/11] bcache: fix potential div-zero error of + writeback_rate_i_term_inverse + +dc->writeback_rate_i_term_inverse can be set via sysfs interface. It is +in type unsigned int, and convert from input string by d_strtoul(). The +problem is d_strtoul() does not check valid range of the input, if +4294967296 is written into sysfs file writeback_rate_i_term_inverse, +an overflow of unsigned integer will happen and value 0 is set to +dc->writeback_rate_i_term_inverse. + +In writeback.c:__update_writeback_rate(), there are following lines of +code, + integral_scaled = div_s64(dc->writeback_rate_integral, + dc->writeback_rate_i_term_inverse); +If dc->writeback_rate_i_term_inverse is set to 0 via sysfs interface, +a div-zero error might be triggered in the above code. + +Therefore we need to add a range limitation in the sysfs interface, +this is what this patch does, use sysfs_stroul_clamp() to replace +d_strtoul() and restrict the input range in [1, UINT_MAX]. + +Signed-off-by: Coly Li <colyli@suse.de> +--- + drivers/md/bcache/sysfs.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c +index 6a1774a6c5fa..0a7fa6fc3660 100644 +--- a/drivers/md/bcache/sysfs.c ++++ b/drivers/md/bcache/sysfs.c +@@ -298,7 +298,9 @@ STORE(__cached_dev) + sysfs_strtoul_clamp(writeback_rate_update_seconds, + dc->writeback_rate_update_seconds, + 1, WRITEBACK_RATE_UPDATE_SECS_MAX); +- d_strtoul(writeback_rate_i_term_inverse); ++ sysfs_strtoul_clamp(writeback_rate_i_term_inverse, ++ dc->writeback_rate_i_term_inverse, ++ 1, UINT_MAX); + d_strtoul_nonzero(writeback_rate_p_term_inverse); + d_strtoul_nonzero(writeback_rate_minimum); + +-- +2.16.4 + diff --git a/for-next/sysfs-fix/0007-bcache-fix-potential-div-zero-error-of-writeback_rat.patch b/for-next/sysfs-fix/0007-bcache-fix-potential-div-zero-error-of-writeback_rat.patch new file mode 100644 index 0000000..ace013f --- /dev/null +++ b/for-next/sysfs-fix/0007-bcache-fix-potential-div-zero-error-of-writeback_rat.patch @@ -0,0 +1,45 @@ +From c0191ef6afbaca291b5e7654275306383ebeda6f Mon Sep 17 00:00:00 2001 +From: Coly Li <colyli@suse.de> +Date: Thu, 20 Dec 2018 20:48:38 +0800 +Subject: [PATCH 07/11] bcache: fix potential div-zero error of + writeback_rate_p_term_inverse + +Current code already uses d_strtoul_nonzero() to convert input string +to an unsigned integer, to make sure writeback_rate_p_term_inverse +won't be zero value. But overflow may happen when converting input +string to an unsigned integer value by d_strtoul_nonzero(), then +dc->writeback_rate_p_term_inverse can still be set to 0 even if the +sysfs file input value is not zero, e.g. 4294967296 (a.k.a UINT_MAX+1). + +If dc->writeback_rate_p_term_inverse is set to 0, it might cause a +dev-zero error in following code from __update_writeback_rate(), + int64_t proportional_scaled = + div_s64(error, dc->writeback_rate_p_term_inverse); + +This patch replaces d_strtoul_nonzero() by sysfs_strtoul_clamp() and +limit the value range in [1, UINT_MAX]. Then the unsigned integer +overflow and dev-zero error can be avoided. + +Signed-off-by: Coly Li <colyli@suse.de> +--- + drivers/md/bcache/sysfs.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c +index 0a7fa6fc3660..0a1c90d9c8a6 100644 +--- a/drivers/md/bcache/sysfs.c ++++ b/drivers/md/bcache/sysfs.c +@@ -301,7 +301,9 @@ STORE(__cached_dev) + sysfs_strtoul_clamp(writeback_rate_i_term_inverse, + dc->writeback_rate_i_term_inverse, + 1, UINT_MAX); +- d_strtoul_nonzero(writeback_rate_p_term_inverse); ++ sysfs_strtoul_clamp(writeback_rate_p_term_inverse, ++ dc->writeback_rate_p_term_inverse, ++ 1, UINT_MAX); + d_strtoul_nonzero(writeback_rate_minimum); + + sysfs_strtoul_clamp(io_error_limit, dc->error_limit, 0, INT_MAX); +-- +2.16.4 + diff --git a/for-next/sysfs-fix/0008-bcache-fix-input-overflow-to-writeback_rate_minimum.patch b/for-next/sysfs-fix/0008-bcache-fix-input-overflow-to-writeback_rate_minimum.patch new file mode 100644 index 0000000..2d0e347 --- /dev/null +++ b/for-next/sysfs-fix/0008-bcache-fix-input-overflow-to-writeback_rate_minimum.patch @@ -0,0 +1,37 @@ +From efaae8ee5d752d1e9398e706d31d3e36f6ee5e7b Mon Sep 17 00:00:00 2001 +From: Coly Li <colyli@suse.de> +Date: Thu, 20 Dec 2018 21:06:41 +0800 +Subject: [PATCH 08/11] bcache: fix input overflow to writeback_rate_minimum + +dc->writeback_rate_minimum is type unsigned integer variable, it is set +via sysfs interface, and converte from input string to unsigned integer +by d_strtoul_nonzero(). When the converted input value is larger than +UINT_MAX, overflow to unsigned integer happens. + +This patch fixes the overflow by using sysfs_strotoul_clamp() to +convert input string and limit the value in range [1, UINT_MAX], then +the overflow can be avoided. + +Signed-off-by: Coly Li <colyli@suse.de> +--- + drivers/md/bcache/sysfs.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c +index 0a1c90d9c8a6..aacb0e2fc81c 100644 +--- a/drivers/md/bcache/sysfs.c ++++ b/drivers/md/bcache/sysfs.c +@@ -304,7 +304,9 @@ STORE(__cached_dev) + sysfs_strtoul_clamp(writeback_rate_p_term_inverse, + dc->writeback_rate_p_term_inverse, + 1, UINT_MAX); +- d_strtoul_nonzero(writeback_rate_minimum); ++ sysfs_strtoul_clamp(writeback_rate_minimum, ++ dc->writeback_rate_minimum, ++ 1, UINT_MAX); + + sysfs_strtoul_clamp(io_error_limit, dc->error_limit, 0, INT_MAX); + +-- +2.16.4 + diff --git a/for-next/sysfs-fix/0009-bcache-fix-input-overflow-to-journal_delay_ms.patch b/for-next/sysfs-fix/0009-bcache-fix-input-overflow-to-journal_delay_ms.patch new file mode 100644 index 0000000..7289363 --- /dev/null +++ b/for-next/sysfs-fix/0009-bcache-fix-input-overflow-to-journal_delay_ms.patch @@ -0,0 +1,38 @@ +From 04dc409a9b7681c3ffa7eaa504cf342fb39950f3 Mon Sep 17 00:00:00 2001 +From: Coly Li <colyli@suse.de> +Date: Thu, 20 Dec 2018 21:30:56 +0800 +Subject: [PATCH 09/11] bcache: fix input overflow to journal_delay_ms + +c->journal_delay_ms is in type unsigned short, it is set via sysfs +interface and converted by sysfs_strtoul() from input string to +unsigned short value. Therefore overflow to unsigned short might be +happen when the converted value exceed USHRT_MAX. e.g. writting +65536 into sysfs file journal_delay_ms, c->journal_delay_ms is set to +0. + +This patch uses sysfs_strtoul_clamp() to convert the input string and +limit value range in [0, USHRT_MAX], to avoid the input overflow. + +Signed-off-by: Coly Li <colyli@suse.de> +--- + drivers/md/bcache/sysfs.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c +index aacb0e2fc81c..db12d4210a20 100644 +--- a/drivers/md/bcache/sysfs.c ++++ b/drivers/md/bcache/sysfs.c +@@ -809,7 +809,9 @@ STORE(__bch_cache_set) + } + } + +- sysfs_strtoul(journal_delay_ms, c->journal_delay_ms); ++ sysfs_strtoul_clamp(journal_delay_ms, ++ c->journal_delay_ms, ++ 0, USHRT_MAX); + sysfs_strtoul_bool(verify, c->verify); + sysfs_strtoul_bool(key_merging_disabled,c->key_merging_disabled); + sysfs_strtoul(expensive_debug_checks, c->expensive_debug_checks); +-- +2.16.4 + diff --git a/for-next/sysfs-fix/0010-bcache-fix-input-overflow-to-cache-set-io_error_limi.patch b/for-next/sysfs-fix/0010-bcache-fix-input-overflow-to-cache-set-io_error_limi.patch new file mode 100644 index 0000000..9958aef --- /dev/null +++ b/for-next/sysfs-fix/0010-bcache-fix-input-overflow-to-cache-set-io_error_limi.patch @@ -0,0 +1,38 @@ +From 3d2d57ad08a4f19fb557cd99a3ddceb938bd1266 Mon Sep 17 00:00:00 2001 +From: Coly Li <colyli@suse.de> +Date: Thu, 20 Dec 2018 22:08:50 +0800 +Subject: [PATCH 10/11] bcache: fix input overflow to cache set io_error_limit + +c->error_limit is in type unsigned int, it is set via cache set sysfs +file io_error_limit. Inside the bcache code, input string is converted +by strtoul_or_return() and set the converted value to c->error_limit. + +Because the converted value is unsigned long, and c->error_limit is +unsigned int, if the input is large enought, overflow will happen to +c->error_limit. + +This patch uses sysfs_strtoul_clamp() to convert input string, and set +the range in [0, UINT_MAX] to avoid the potential overflow. + +Signed-off-by: Coly Li <colyli@suse.de> +--- + drivers/md/bcache/sysfs.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c +index db12d4210a20..9c80e816de5d 100644 +--- a/drivers/md/bcache/sysfs.c ++++ b/drivers/md/bcache/sysfs.c +@@ -789,8 +789,7 @@ STORE(__bch_cache_set) + c->on_error = v; + } + +- if (attr == &sysfs_io_error_limit) +- c->error_limit = strtoul_or_return(buf); ++ sysfs_strtoul_clamp(io_error_limit, c->error_limit, 0, UINT_MAX); + + /* See count_io_errors() for why 88 */ + if (attr == &sysfs_io_error_halflife) +-- +2.16.4 + diff --git a/for-next/sysfs-fix/0011-bcache-fix-input-overflow-to-cache-set-sysfs-file-io.patch b/for-next/sysfs-fix/0011-bcache-fix-input-overflow-to-cache-set-sysfs-file-io.patch new file mode 100644 index 0000000..4eebdaf --- /dev/null +++ b/for-next/sysfs-fix/0011-bcache-fix-input-overflow-to-cache-set-sysfs-file-io.patch @@ -0,0 +1,44 @@ +From 3eb7a1339e1f928f91c6479523daf5bea97c66b0 Mon Sep 17 00:00:00 2001 +From: Coly Li <colyli@suse.de> +Date: Thu, 20 Dec 2018 22:31:25 +0800 +Subject: [PATCH 11/11] bcache: fix input overflow to cache set sysfs file + io_error_halflife + +Cache set sysfs entry io_error_halflife is used to set c->error_decay. +c->error_decay is in type unsinged int, and it is converted by +strtoul_or_return(), therefore overflow to c->error_decay is possible +for a large input value. + +This patch fixes the overflow by using strtoul_safe_clamp() to convert +input string to an unsigned long value in range [0, UINT_MAX], then +divides by 88 and set it to c->error_decay. + +Signed-off-by: Coly Li <colyli@suse.de> +--- + drivers/md/bcache/sysfs.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c +index 9c80e816de5d..0e8e18b7b38a 100644 +--- a/drivers/md/bcache/sysfs.c ++++ b/drivers/md/bcache/sysfs.c +@@ -792,8 +792,14 @@ STORE(__bch_cache_set) + sysfs_strtoul_clamp(io_error_limit, c->error_limit, 0, UINT_MAX); + + /* See count_io_errors() for why 88 */ +- if (attr == &sysfs_io_error_halflife) +- c->error_decay = strtoul_or_return(buf) / 88; ++ if (attr == &sysfs_io_error_halflife) { ++ unsigned long v; ++ ++ v = strtoul_safe_clamp(buf, v, 0, UINT_MAX); ++ if (v < 0) ++ return v; ++ c->error_decay = v / 88; ++ } + + if (attr == &sysfs_io_disable) { + v = strtoul_or_return(buf); +-- +2.16.4 + diff --git a/for-test/0001-bcache-add-w_data_avg.patch b/for-test/0001-bcache-add-w_data_avg.patch new file mode 100644 index 0000000..3b6e089 --- /dev/null +++ b/for-test/0001-bcache-add-w_data_avg.patch @@ -0,0 +1,91 @@ +From 47e164ffcae5dc3e03bff72a0787652fa5aaf057 Mon Sep 17 00:00:00 2001 +From: Coly Li <colyli@suse.de> +Date: Fri, 7 Dec 2018 23:52:39 +0800 +Subject: [PATCH] bcache: add w_data_avg + +To record average write size for journal w[]->data. + +Signed-off-by: Coly Li <colyli@suse.de> +--- + drivers/md/bcache/journal.c | 8 +++++++- + drivers/md/bcache/journal.h | 1 + + drivers/md/bcache/sysfs.c | 4 ++++ + 3 files changed, 12 insertions(+), 1 deletion(-) + +diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c +index 522c7426f3a0..569aa1484ac0 100644 +--- a/drivers/md/bcache/journal.c ++++ b/drivers/md/bcache/journal.c +@@ -613,7 +613,7 @@ static void journal_write_unlocked(struct closure *cl) + struct bkey *k = &c->journal.key; + unsigned int i, sectors = set_blocks(w->data, block_bytes(c)) * + c->sb.block_size; +- ++ int w_data_avg; + struct bio *bio; + struct bio_list list; + +@@ -671,6 +671,11 @@ static void journal_write_unlocked(struct closure *cl) + ca->journal.seq[ca->journal.cur_idx] = w->data->seq; + } + ++ /* record average size of written w->data in sectors */ ++ w_data_avg = atomic_read(&c->journal.w_data_avg); ++ w_data_avg = ewma_add(w_data_avg, sectors, 8, 4); ++ atomic_set(&c->journal.w_data_avg, w_data_avg); ++ + atomic_dec_bug(&fifo_back(&c->journal.pin)); + bch_journal_next(&c->journal); + journal_reclaim(c); +@@ -845,6 +850,7 @@ int bch_journal_alloc(struct cache_set *c) + + j->w[0].c = c; + j->w[1].c = c; ++ atomic_set(&j->w_data_avg, 0); + + if (!(init_heap(&c->flush_btree, 128, GFP_KERNEL)) || + !(init_fifo(&j->pin, JOURNAL_PIN, GFP_KERNEL)) || +diff --git a/drivers/md/bcache/journal.h b/drivers/md/bcache/journal.h +index 66f0facff84b..3be9d7f72d5a 100644 +--- a/drivers/md/bcache/journal.h ++++ b/drivers/md/bcache/journal.h +@@ -117,6 +117,7 @@ struct journal { + BKEY_PADDED(key); + + struct journal_write w[2], *cur; ++ atomic_t w_data_avg; + }; + + /* +diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c +index 26f035a0c5b9..d3b56cd3b794 100644 +--- a/drivers/md/bcache/sysfs.c ++++ b/drivers/md/bcache/sysfs.c +@@ -67,6 +67,7 @@ read_attribute(written); + read_attribute(btree_written); + read_attribute(metadata_written); + read_attribute(active_journal_entries); ++read_attribute(w_data_avg); + + sysfs_time_stats_attribute(btree_gc, sec, ms); + sysfs_time_stats_attribute(btree_split, sec, us); +@@ -669,6 +670,8 @@ SHOW(__bch_cache_set) + c->congested_write_threshold_us); + + sysfs_print(active_journal_entries, fifo_used(&c->journal.pin)); ++ sysfs_print(w_data_avg, ++ atomic_read(&c->journal.w_data_avg)); + sysfs_printf(verify, "%i", c->verify); + sysfs_printf(key_merging_disabled, "%i", c->key_merging_disabled); + sysfs_printf(expensive_debug_checks, +@@ -841,6 +844,7 @@ KTYPE(bch_cache_set); + + static struct attribute *bch_cache_set_internal_files[] = { + &sysfs_active_journal_entries, ++ &sysfs_w_data_avg, + + sysfs_time_stats_attribute_list(btree_gc, sec, ms) + sysfs_time_stats_attribute_list(btree_split, sec, us) +-- +2.16.4 + |