Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mm/damon/lru_sort: fix quota status loss due to online tunings

For online parameters change, DAMON_LRU_SORT creates new schemes based on
latest values of the parameters and replaces the old schemes with the new
one. When creating it, the internal status of the quotas of the old
schemes is not preserved. As a result, charging of the quota starts from
zero after the online tuning. The data that collected to estimate the
throughput of the scheme's action is also reset, and therefore the
estimation should start from the scratch again. Because the throughput
estimation is being used to convert the time quota to the effective size
quota, this could result in temporal time quota inaccuracy. It would be
recovered over time, though. In short, the quota accuracy could be
temporarily degraded after online parameters update.

Fix the problem by checking the case and copying the internal fields for
the status.

Link: https://lkml.kernel.org/r/20240216194025.9207-3-sj@kernel.org
Fixes: 40e983cca927 ("mm/damon: introduce DAMON-based LRU-lists Sorting")
Signed-off-by: SeongJae Park <sj@kernel.org>
Cc: <stable@vger.kernel.org> [6.0+]
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

SeongJae Park and committed by
Andrew Morton
13d0599a 1b0ca4e4

+36 -7
+36 -7
mm/damon/lru_sort.c
··· 185 185 return damon_lru_sort_new_scheme(&pattern, DAMOS_LRU_DEPRIO); 186 186 } 187 187 188 + static void damon_lru_sort_copy_quota_status(struct damos_quota *dst, 189 + struct damos_quota *src) 190 + { 191 + dst->total_charged_sz = src->total_charged_sz; 192 + dst->total_charged_ns = src->total_charged_ns; 193 + dst->charged_sz = src->charged_sz; 194 + dst->charged_from = src->charged_from; 195 + dst->charge_target_from = src->charge_target_from; 196 + dst->charge_addr_from = src->charge_addr_from; 197 + } 198 + 188 199 static int damon_lru_sort_apply_parameters(void) 189 200 { 190 - struct damos *scheme; 201 + struct damos *scheme, *hot_scheme, *cold_scheme; 202 + struct damos *old_hot_scheme = NULL, *old_cold_scheme = NULL; 191 203 unsigned int hot_thres, cold_thres; 192 204 int err = 0; 193 205 ··· 207 195 if (err) 208 196 return err; 209 197 198 + damon_for_each_scheme(scheme, ctx) { 199 + if (!old_hot_scheme) { 200 + old_hot_scheme = scheme; 201 + continue; 202 + } 203 + old_cold_scheme = scheme; 204 + } 205 + 210 206 hot_thres = damon_max_nr_accesses(&damon_lru_sort_mon_attrs) * 211 207 hot_thres_access_freq / 1000; 212 - scheme = damon_lru_sort_new_hot_scheme(hot_thres); 213 - if (!scheme) 208 + hot_scheme = damon_lru_sort_new_hot_scheme(hot_thres); 209 + if (!hot_scheme) 214 210 return -ENOMEM; 215 - damon_set_schemes(ctx, &scheme, 1); 211 + if (old_hot_scheme) 212 + damon_lru_sort_copy_quota_status(&hot_scheme->quota, 213 + &old_hot_scheme->quota); 216 214 217 215 cold_thres = cold_min_age / damon_lru_sort_mon_attrs.aggr_interval; 218 - scheme = damon_lru_sort_new_cold_scheme(cold_thres); 219 - if (!scheme) 216 + cold_scheme = damon_lru_sort_new_cold_scheme(cold_thres); 217 + if (!cold_scheme) { 218 + damon_destroy_scheme(hot_scheme); 220 219 return -ENOMEM; 221 - damon_add_scheme(ctx, scheme); 220 + } 221 + if (old_cold_scheme) 222 + damon_lru_sort_copy_quota_status(&cold_scheme->quota, 223 + &old_cold_scheme->quota); 224 + 225 + damon_set_schemes(ctx, &hot_scheme, 1); 226 + damon_add_scheme(ctx, cold_scheme); 222 227 223 228 return damon_set_region_biggest_system_ram_default(target, 224 229 &monitor_region_start,