mm: use part per 1000000 for bdi ratios
authorStefan Roesch <shr@devkernel.io>
Sat, 19 Nov 2022 00:51:59 +0000 (16:51 -0800)
committerAndrew Morton <akpm@linux-foundation.org>
Wed, 30 Nov 2022 23:59:03 +0000 (15:59 -0800)
To get finer granularity for ratio calculations use part per million
instead of percentiles. This is especially important if we want to
automatically convert byte values to ratios. Otherwise the values that
are actually used can be quite different. This is also important for
machines with more main memory (1% of 256GB is already 2.5GB).

Link: https://lkml.kernel.org/r/20221119005215.3052436-5-shr@devkernel.io
Signed-off-by: Stefan Roesch <shr@devkernel.io>
Cc: Chris Mason <clm@meta.com>
Cc: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
include/linux/backing-dev.h
mm/backing-dev.c
mm/page-writeback.c

index 9c984ffc8a0aa926ffb975956682d46267a8ff9b..1b50c028e5add88fc8b8c79225a623798696199d 100644 (file)
@@ -102,6 +102,9 @@ static inline unsigned long wb_stat_error(void)
 #endif
 }
 
+/* BDI ratio is expressed as part per 1000000 for finer granularity. */
+#define BDI_RATIO_SCALE 10000
+
 int bdi_set_min_ratio(struct backing_dev_info *bdi, unsigned int min_ratio);
 int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned int max_ratio);
 int bdi_set_strict_limit(struct backing_dev_info *bdi, unsigned int strict_limit);
index a0899cce72ef9ee62b1c9a10119d3cc84c87b30a..90fa517123dc60bba1e17e8973377fa3a5da6c8c 100644 (file)
@@ -178,7 +178,7 @@ static ssize_t min_ratio_store(struct device *dev,
 
        return ret;
 }
-BDI_SHOW(min_ratio, bdi->min_ratio)
+BDI_SHOW(min_ratio, bdi->min_ratio / BDI_RATIO_SCALE)
 
 static ssize_t max_ratio_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t count)
@@ -197,7 +197,7 @@ static ssize_t max_ratio_store(struct device *dev,
 
        return ret;
 }
-BDI_SHOW(max_ratio, bdi->max_ratio)
+BDI_SHOW(max_ratio, bdi->max_ratio / BDI_RATIO_SCALE)
 
 static ssize_t stable_pages_required_show(struct device *dev,
                                          struct device_attribute *attr,
@@ -809,7 +809,7 @@ int bdi_init(struct backing_dev_info *bdi)
 
        kref_init(&bdi->refcnt);
        bdi->min_ratio = 0;
-       bdi->max_ratio = 100;
+       bdi->max_ratio = 100 * BDI_RATIO_SCALE;
        bdi->max_prop_frac = FPROP_FRAC_BASE;
        INIT_LIST_HEAD(&bdi->bdi_list);
        INIT_LIST_HEAD(&bdi->wb_list);
index 3745b886722f8c50feffb30b556f7a2aff123d15..dd98b26543027ac51cfe7a2a174c57d4035a3e80 100644 (file)
@@ -197,7 +197,7 @@ static void wb_min_max_ratio(struct bdi_writeback *wb,
                        min *= this_bw;
                        min = div64_ul(min, tot_bw);
                }
-               if (max < 100) {
+               if (max < 100 * BDI_RATIO_SCALE) {
                        max *= this_bw;
                        max = div64_ul(max, tot_bw);
                }
@@ -655,6 +655,8 @@ int bdi_set_min_ratio(struct backing_dev_info *bdi, unsigned int min_ratio)
        unsigned int delta;
        int ret = 0;
 
+       min_ratio *= BDI_RATIO_SCALE;
+
        spin_lock_bh(&bdi_lock);
        if (min_ratio > bdi->max_ratio) {
                ret = -EINVAL;
@@ -665,7 +667,7 @@ int bdi_set_min_ratio(struct backing_dev_info *bdi, unsigned int min_ratio)
                        bdi->min_ratio = min_ratio;
                } else {
                        delta = min_ratio - bdi->min_ratio;
-                       if (bdi_min_ratio + delta < 100) {
+                       if (bdi_min_ratio + delta < 100 * BDI_RATIO_SCALE) {
                                bdi_min_ratio += delta;
                                bdi->min_ratio = min_ratio;
                        } else {
@@ -684,6 +686,7 @@ int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned max_ratio)
 
        if (max_ratio > 100)
                return -EINVAL;
+       max_ratio *= BDI_RATIO_SCALE;
 
        spin_lock_bh(&bdi_lock);
        if (bdi->min_ratio > max_ratio) {
@@ -775,15 +778,15 @@ static unsigned long __wb_calc_thresh(struct dirty_throttle_control *dtc)
        fprop_fraction_percpu(&dom->completions, dtc->wb_completions,
                              &numerator, &denominator);
 
-       wb_thresh = (thresh * (100 - bdi_min_ratio)) / 100;
+       wb_thresh = (thresh * (100 * BDI_RATIO_SCALE - bdi_min_ratio)) / (100 * BDI_RATIO_SCALE);
        wb_thresh *= numerator;
        wb_thresh = div64_ul(wb_thresh, denominator);
 
        wb_min_max_ratio(dtc->wb, &wb_min_ratio, &wb_max_ratio);
 
-       wb_thresh += (thresh * wb_min_ratio) / 100;
-       if (wb_thresh > (thresh * wb_max_ratio) / 100)
-               wb_thresh = thresh * wb_max_ratio / 100;
+       wb_thresh += (thresh * wb_min_ratio) / (100 * BDI_RATIO_SCALE);
+       if (wb_thresh > (thresh * wb_max_ratio) / (100 * BDI_RATIO_SCALE))
+               wb_thresh = thresh * wb_max_ratio / (100 * BDI_RATIO_SCALE);
 
        return wb_thresh;
 }