xref: /linux/mm/damon/lru_sort.c (revision 79790b6818e96c58fe2bffee1b418c16e64e7b80)
140e983ccSSeongJae Park // SPDX-License-Identifier: GPL-2.0
240e983ccSSeongJae Park /*
340e983ccSSeongJae Park  * DAMON-based LRU-lists Sorting
440e983ccSSeongJae Park  *
540e983ccSSeongJae Park  * Author: SeongJae Park <sj@kernel.org>
640e983ccSSeongJae Park  */
740e983ccSSeongJae Park 
840e983ccSSeongJae Park #define pr_fmt(fmt) "damon-lru-sort: " fmt
940e983ccSSeongJae Park 
1040e983ccSSeongJae Park #include <linux/damon.h>
11e6aff38bSChristophe JAILLET #include <linux/kstrtox.h>
1240e983ccSSeongJae Park #include <linux/module.h>
1340e983ccSSeongJae Park 
1495f7c05dSSeongJae Park #include "modules-common.h"
1595f7c05dSSeongJae Park 
1640e983ccSSeongJae Park #ifdef MODULE_PARAM_PREFIX
1740e983ccSSeongJae Park #undef MODULE_PARAM_PREFIX
1840e983ccSSeongJae Park #endif
1940e983ccSSeongJae Park #define MODULE_PARAM_PREFIX "damon_lru_sort."
2040e983ccSSeongJae Park 
2140e983ccSSeongJae Park /*
2240e983ccSSeongJae Park  * Enable or disable DAMON_LRU_SORT.
2340e983ccSSeongJae Park  *
2440e983ccSSeongJae Park  * You can enable DAMON_LRU_SORT by setting the value of this parameter as
2540e983ccSSeongJae Park  * ``Y``.  Setting it as ``N`` disables DAMON_LRU_SORT.  Note that
2640e983ccSSeongJae Park  * DAMON_LRU_SORT could do no real monitoring and LRU-lists sorting due to the
2740e983ccSSeongJae Park  * watermarks-based activation condition.  Refer to below descriptions for the
2840e983ccSSeongJae Park  * watermarks parameter for this.
2940e983ccSSeongJae Park  */
3040e983ccSSeongJae Park static bool enabled __read_mostly;
3140e983ccSSeongJae Park 
3240e983ccSSeongJae Park /*
3340e983ccSSeongJae Park  * Make DAMON_LRU_SORT reads the input parameters again, except ``enabled``.
3440e983ccSSeongJae Park  *
3540e983ccSSeongJae Park  * Input parameters that updated while DAMON_LRU_SORT is running are not
3640e983ccSSeongJae Park  * applied by default.  Once this parameter is set as ``Y``, DAMON_LRU_SORT
3740e983ccSSeongJae Park  * reads values of parametrs except ``enabled`` again.  Once the re-reading is
3840e983ccSSeongJae Park  * done, this parameter is set as ``N``.  If invalid parameters are found while
3940e983ccSSeongJae Park  * the re-reading, DAMON_LRU_SORT will be disabled.
4040e983ccSSeongJae Park  */
4140e983ccSSeongJae Park static bool commit_inputs __read_mostly;
4240e983ccSSeongJae Park module_param(commit_inputs, bool, 0600);
4340e983ccSSeongJae Park 
4440e983ccSSeongJae Park /*
4540e983ccSSeongJae Park  * Access frequency threshold for hot memory regions identification in permil.
4640e983ccSSeongJae Park  *
4740e983ccSSeongJae Park  * If a memory region is accessed in frequency of this or higher,
4840e983ccSSeongJae Park  * DAMON_LRU_SORT identifies the region as hot, and mark it as accessed on the
4940e983ccSSeongJae Park  * LRU list, so that it could not be reclaimed under memory pressure.  50% by
5040e983ccSSeongJae Park  * default.
5140e983ccSSeongJae Park  */
5240e983ccSSeongJae Park static unsigned long hot_thres_access_freq = 500;
5340e983ccSSeongJae Park module_param(hot_thres_access_freq, ulong, 0600);
5440e983ccSSeongJae Park 
5540e983ccSSeongJae Park /*
5640e983ccSSeongJae Park  * Time threshold for cold memory regions identification in microseconds.
5740e983ccSSeongJae Park  *
5840e983ccSSeongJae Park  * If a memory region is not accessed for this or longer time, DAMON_LRU_SORT
5940e983ccSSeongJae Park  * identifies the region as cold, and mark it as unaccessed on the LRU list, so
6040e983ccSSeongJae Park  * that it could be reclaimed first under memory pressure.  120 seconds by
6140e983ccSSeongJae Park  * default.
6240e983ccSSeongJae Park  */
6340e983ccSSeongJae Park static unsigned long cold_min_age __read_mostly = 120000000;
6440e983ccSSeongJae Park module_param(cold_min_age, ulong, 0600);
6540e983ccSSeongJae Park 
6645b8212fSSeongJae Park static struct damos_quota damon_lru_sort_quota = {
6745b8212fSSeongJae Park 	/* Use up to 10 ms per 1 sec, by default */
6845b8212fSSeongJae Park 	.ms = 10,
6945b8212fSSeongJae Park 	.sz = 0,
7045b8212fSSeongJae Park 	.reset_interval = 1000,
7145b8212fSSeongJae Park 	/* Within the quota, mark hotter regions accessed first. */
7245b8212fSSeongJae Park 	.weight_sz = 0,
7345b8212fSSeongJae Park 	.weight_nr_accesses = 1,
7445b8212fSSeongJae Park 	.weight_age = 0,
7545b8212fSSeongJae Park };
7645b8212fSSeongJae Park DEFINE_DAMON_MODULES_DAMOS_TIME_QUOTA(damon_lru_sort_quota);
7740e983ccSSeongJae Park 
78e47b0825SYang Yingliang static struct damos_watermarks damon_lru_sort_wmarks = {
796517d2d9SSeongJae Park 	.metric = DAMOS_WMARK_FREE_MEM_RATE,
806517d2d9SSeongJae Park 	.interval = 5000000,	/* 5 seconds */
816517d2d9SSeongJae Park 	.high = 200,		/* 20 percent */
826517d2d9SSeongJae Park 	.mid = 150,		/* 15 percent */
836517d2d9SSeongJae Park 	.low = 50,		/* 5 percent */
846517d2d9SSeongJae Park };
856517d2d9SSeongJae Park DEFINE_DAMON_MODULES_WMARKS_PARAMS(damon_lru_sort_wmarks);
8640e983ccSSeongJae Park 
87135e128fSSeongJae Park static struct damon_attrs damon_lru_sort_mon_attrs = {
8895f7c05dSSeongJae Park 	.sample_interval = 5000,	/* 5 ms */
8995f7c05dSSeongJae Park 	.aggr_interval = 100000,	/* 100 ms */
90135e128fSSeongJae Park 	.ops_update_interval = 0,
91135e128fSSeongJae Park 	.min_nr_regions = 10,
92135e128fSSeongJae Park 	.max_nr_regions = 1000,
93135e128fSSeongJae Park };
9495f7c05dSSeongJae Park DEFINE_DAMON_MODULES_MON_ATTRS_PARAMS(damon_lru_sort_mon_attrs);
9540e983ccSSeongJae Park 
9640e983ccSSeongJae Park /*
9740e983ccSSeongJae Park  * Start of the target memory region in physical address.
9840e983ccSSeongJae Park  *
9940e983ccSSeongJae Park  * The start physical address of memory region that DAMON_LRU_SORT will do work
10040e983ccSSeongJae Park  * against.  By default, biggest System RAM is used as the region.
10140e983ccSSeongJae Park  */
10240e983ccSSeongJae Park static unsigned long monitor_region_start __read_mostly;
10340e983ccSSeongJae Park module_param(monitor_region_start, ulong, 0600);
10440e983ccSSeongJae Park 
10540e983ccSSeongJae Park /*
10640e983ccSSeongJae Park  * End of the target memory region in physical address.
10740e983ccSSeongJae Park  *
10840e983ccSSeongJae Park  * The end physical address of memory region that DAMON_LRU_SORT will do work
10940e983ccSSeongJae Park  * against.  By default, biggest System RAM is used as the region.
11040e983ccSSeongJae Park  */
11140e983ccSSeongJae Park static unsigned long monitor_region_end __read_mostly;
11240e983ccSSeongJae Park module_param(monitor_region_end, ulong, 0600);
11340e983ccSSeongJae Park 
11440e983ccSSeongJae Park /*
11540e983ccSSeongJae Park  * PID of the DAMON thread
11640e983ccSSeongJae Park  *
11740e983ccSSeongJae Park  * If DAMON_LRU_SORT is enabled, this becomes the PID of the worker thread.
11840e983ccSSeongJae Park  * Else, -1.
11940e983ccSSeongJae Park  */
12040e983ccSSeongJae Park static int kdamond_pid __read_mostly = -1;
12140e983ccSSeongJae Park module_param(kdamond_pid, int, 0400);
12240e983ccSSeongJae Park 
123dd172fbfSSeongJae Park static struct damos_stat damon_lru_sort_hot_stat;
124dd172fbfSSeongJae Park DEFINE_DAMON_MODULES_DAMOS_STATS_PARAMS(damon_lru_sort_hot_stat,
125dd172fbfSSeongJae Park 		lru_sort_tried_hot_regions, lru_sorted_hot_regions,
126dd172fbfSSeongJae Park 		hot_quota_exceeds);
12740e983ccSSeongJae Park 
128dd172fbfSSeongJae Park static struct damos_stat damon_lru_sort_cold_stat;
129dd172fbfSSeongJae Park DEFINE_DAMON_MODULES_DAMOS_STATS_PARAMS(damon_lru_sort_cold_stat,
130dd172fbfSSeongJae Park 		lru_sort_tried_cold_regions, lru_sorted_cold_regions,
131dd172fbfSSeongJae Park 		cold_quota_exceeds);
13240e983ccSSeongJae Park 
133a07b8eafSXin Hao static struct damos_access_pattern damon_lru_sort_stub_pattern = {
134a07b8eafSXin Hao 	/* Find regions having PAGE_SIZE or larger size */
135a07b8eafSXin Hao 	.min_sz_region = PAGE_SIZE,
136a07b8eafSXin Hao 	.max_sz_region = ULONG_MAX,
137a07b8eafSXin Hao 	/* no matter its access frequency */
138a07b8eafSXin Hao 	.min_nr_accesses = 0,
139a07b8eafSXin Hao 	.max_nr_accesses = UINT_MAX,
140a07b8eafSXin Hao 	/* no matter its age */
141a07b8eafSXin Hao 	.min_age_region = 0,
142a07b8eafSXin Hao 	.max_age_region = UINT_MAX,
143a07b8eafSXin Hao };
144a07b8eafSXin Hao 
14540e983ccSSeongJae Park static struct damon_ctx *ctx;
14640e983ccSSeongJae Park static struct damon_target *target;
14740e983ccSSeongJae Park 
damon_lru_sort_new_scheme(struct damos_access_pattern * pattern,enum damos_action action)148a62518abSSeongJae Park static struct damos *damon_lru_sort_new_scheme(
149a62518abSSeongJae Park 		struct damos_access_pattern *pattern, enum damos_action action)
150a62518abSSeongJae Park {
151a62518abSSeongJae Park 	struct damos_quota quota = damon_lru_sort_quota;
152a62518abSSeongJae Park 
153a62518abSSeongJae Park 	/* Use half of total quota for hot/cold pages sorting */
154a62518abSSeongJae Park 	quota.ms = quota.ms / 2;
155a62518abSSeongJae Park 
156a62518abSSeongJae Park 	return damon_new_scheme(
157a62518abSSeongJae Park 			/* find the pattern, and */
158a62518abSSeongJae Park 			pattern,
159a62518abSSeongJae Park 			/* (de)prioritize on LRU-lists */
160a62518abSSeongJae Park 			action,
16142f994b7SSeongJae Park 			/* for each aggregation interval */
16242f994b7SSeongJae Park 			0,
163a62518abSSeongJae Park 			/* under the quota. */
164a62518abSSeongJae Park 			&quota,
165a62518abSSeongJae Park 			/* (De)activate this according to the watermarks. */
166a62518abSSeongJae Park 			&damon_lru_sort_wmarks);
167a62518abSSeongJae Park }
168a62518abSSeongJae Park 
16940e983ccSSeongJae Park /* Create a DAMON-based operation scheme for hot memory regions */
damon_lru_sort_new_hot_scheme(unsigned int hot_thres)17040e983ccSSeongJae Park static struct damos *damon_lru_sort_new_hot_scheme(unsigned int hot_thres)
17140e983ccSSeongJae Park {
172a07b8eafSXin Hao 	struct damos_access_pattern pattern = damon_lru_sort_stub_pattern;
17345b8212fSSeongJae Park 
174a07b8eafSXin Hao 	pattern.min_nr_accesses = hot_thres;
175a62518abSSeongJae Park 	return damon_lru_sort_new_scheme(&pattern, DAMOS_LRU_PRIO);
17640e983ccSSeongJae Park }
17740e983ccSSeongJae Park 
17840e983ccSSeongJae Park /* Create a DAMON-based operation scheme for cold memory regions */
damon_lru_sort_new_cold_scheme(unsigned int cold_thres)17940e983ccSSeongJae Park static struct damos *damon_lru_sort_new_cold_scheme(unsigned int cold_thres)
18040e983ccSSeongJae Park {
181a07b8eafSXin Hao 	struct damos_access_pattern pattern = damon_lru_sort_stub_pattern;
18245b8212fSSeongJae Park 
183a07b8eafSXin Hao 	pattern.max_nr_accesses = 0;
184a07b8eafSXin Hao 	pattern.min_age_region = cold_thres;
185a62518abSSeongJae Park 	return damon_lru_sort_new_scheme(&pattern, DAMOS_LRU_DEPRIO);
18640e983ccSSeongJae Park }
18740e983ccSSeongJae Park 
damon_lru_sort_copy_quota_status(struct damos_quota * dst,struct damos_quota * src)188*13d0599aSSeongJae Park static void damon_lru_sort_copy_quota_status(struct damos_quota *dst,
189*13d0599aSSeongJae Park 		struct damos_quota *src)
190*13d0599aSSeongJae Park {
191*13d0599aSSeongJae Park 	dst->total_charged_sz = src->total_charged_sz;
192*13d0599aSSeongJae Park 	dst->total_charged_ns = src->total_charged_ns;
193*13d0599aSSeongJae Park 	dst->charged_sz = src->charged_sz;
194*13d0599aSSeongJae Park 	dst->charged_from = src->charged_from;
195*13d0599aSSeongJae Park 	dst->charge_target_from = src->charge_target_from;
196*13d0599aSSeongJae Park 	dst->charge_addr_from = src->charge_addr_from;
197*13d0599aSSeongJae Park }
198*13d0599aSSeongJae Park 
damon_lru_sort_apply_parameters(void)19940e983ccSSeongJae Park static int damon_lru_sort_apply_parameters(void)
20040e983ccSSeongJae Park {
201*13d0599aSSeongJae Park 	struct damos *scheme, *hot_scheme, *cold_scheme;
202*13d0599aSSeongJae Park 	struct damos *old_hot_scheme = NULL, *old_cold_scheme = NULL;
20340e983ccSSeongJae Park 	unsigned int hot_thres, cold_thres;
20440e983ccSSeongJae Park 	int err = 0;
20540e983ccSSeongJae Park 
206135e128fSSeongJae Park 	err = damon_set_attrs(ctx, &damon_lru_sort_mon_attrs);
20740e983ccSSeongJae Park 	if (err)
20840e983ccSSeongJae Park 		return err;
20940e983ccSSeongJae Park 
210*13d0599aSSeongJae Park 	damon_for_each_scheme(scheme, ctx) {
211*13d0599aSSeongJae Park 		if (!old_hot_scheme) {
212*13d0599aSSeongJae Park 			old_hot_scheme = scheme;
213*13d0599aSSeongJae Park 			continue;
214*13d0599aSSeongJae Park 		}
215*13d0599aSSeongJae Park 		old_cold_scheme = scheme;
216*13d0599aSSeongJae Park 	}
217*13d0599aSSeongJae Park 
21844063f12SSeongJae Park 	hot_thres = damon_max_nr_accesses(&damon_lru_sort_mon_attrs) *
219135e128fSSeongJae Park 		hot_thres_access_freq / 1000;
220*13d0599aSSeongJae Park 	hot_scheme = damon_lru_sort_new_hot_scheme(hot_thres);
221*13d0599aSSeongJae Park 	if (!hot_scheme)
22240e983ccSSeongJae Park 		return -ENOMEM;
223*13d0599aSSeongJae Park 	if (old_hot_scheme)
224*13d0599aSSeongJae Park 		damon_lru_sort_copy_quota_status(&hot_scheme->quota,
225*13d0599aSSeongJae Park 				&old_hot_scheme->quota);
22640e983ccSSeongJae Park 
227135e128fSSeongJae Park 	cold_thres = cold_min_age / damon_lru_sort_mon_attrs.aggr_interval;
228*13d0599aSSeongJae Park 	cold_scheme = damon_lru_sort_new_cold_scheme(cold_thres);
229*13d0599aSSeongJae Park 	if (!cold_scheme) {
230*13d0599aSSeongJae Park 		damon_destroy_scheme(hot_scheme);
23140e983ccSSeongJae Park 		return -ENOMEM;
232*13d0599aSSeongJae Park 	}
233*13d0599aSSeongJae Park 	if (old_cold_scheme)
234*13d0599aSSeongJae Park 		damon_lru_sort_copy_quota_status(&cold_scheme->quota,
235*13d0599aSSeongJae Park 				&old_cold_scheme->quota);
236*13d0599aSSeongJae Park 
237*13d0599aSSeongJae Park 	damon_set_schemes(ctx, &hot_scheme, 1);
238*13d0599aSSeongJae Park 	damon_add_scheme(ctx, cold_scheme);
23940e983ccSSeongJae Park 
240233f0b31SKaixu Xia 	return damon_set_region_biggest_system_ram_default(target,
241233f0b31SKaixu Xia 					&monitor_region_start,
242233f0b31SKaixu Xia 					&monitor_region_end);
24340e983ccSSeongJae Park }
24440e983ccSSeongJae Park 
damon_lru_sort_turn(bool on)24540e983ccSSeongJae Park static int damon_lru_sort_turn(bool on)
24640e983ccSSeongJae Park {
24740e983ccSSeongJae Park 	int err;
24840e983ccSSeongJae Park 
24940e983ccSSeongJae Park 	if (!on) {
25040e983ccSSeongJae Park 		err = damon_stop(&ctx, 1);
25140e983ccSSeongJae Park 		if (!err)
25240e983ccSSeongJae Park 			kdamond_pid = -1;
25340e983ccSSeongJae Park 		return err;
25440e983ccSSeongJae Park 	}
25540e983ccSSeongJae Park 
25640e983ccSSeongJae Park 	err = damon_lru_sort_apply_parameters();
25740e983ccSSeongJae Park 	if (err)
25840e983ccSSeongJae Park 		return err;
25940e983ccSSeongJae Park 
26040e983ccSSeongJae Park 	err = damon_start(&ctx, 1, true);
26140e983ccSSeongJae Park 	if (err)
26240e983ccSSeongJae Park 		return err;
26340e983ccSSeongJae Park 	kdamond_pid = ctx->kdamond->pid;
26440e983ccSSeongJae Park 	return 0;
26540e983ccSSeongJae Park }
26640e983ccSSeongJae Park 
damon_lru_sort_enabled_store(const char * val,const struct kernel_param * kp)26740e983ccSSeongJae Park static int damon_lru_sort_enabled_store(const char *val,
26840e983ccSSeongJae Park 		const struct kernel_param *kp)
26940e983ccSSeongJae Park {
2707a034fbbSSeongJae Park 	bool is_enabled = enabled;
2717a034fbbSSeongJae Park 	bool enable;
2727a034fbbSSeongJae Park 	int err;
27340e983ccSSeongJae Park 
274e6aff38bSChristophe JAILLET 	err = kstrtobool(val, &enable);
2757a034fbbSSeongJae Park 	if (err)
2767a034fbbSSeongJae Park 		return err;
27740e983ccSSeongJae Park 
2787a034fbbSSeongJae Park 	if (is_enabled == enable)
27940e983ccSSeongJae Park 		return 0;
2807a034fbbSSeongJae Park 
2817a034fbbSSeongJae Park 	/* Called before init function.  The function will handle this. */
2827a034fbbSSeongJae Park 	if (!ctx)
2837a034fbbSSeongJae Park 		goto set_param_out;
2847a034fbbSSeongJae Park 
2857a034fbbSSeongJae Park 	err = damon_lru_sort_turn(enable);
2867a034fbbSSeongJae Park 	if (err)
2877a034fbbSSeongJae Park 		return err;
2887a034fbbSSeongJae Park 
2897a034fbbSSeongJae Park set_param_out:
2907a034fbbSSeongJae Park 	enabled = enable;
2917a034fbbSSeongJae Park 	return err;
29240e983ccSSeongJae Park }
29340e983ccSSeongJae Park 
29440e983ccSSeongJae Park static const struct kernel_param_ops enabled_param_ops = {
29540e983ccSSeongJae Park 	.set = damon_lru_sort_enabled_store,
29640e983ccSSeongJae Park 	.get = param_get_bool,
29740e983ccSSeongJae Park };
29840e983ccSSeongJae Park 
29940e983ccSSeongJae Park module_param_cb(enabled, &enabled_param_ops, &enabled, 0600);
30040e983ccSSeongJae Park MODULE_PARM_DESC(enabled,
30140e983ccSSeongJae Park 	"Enable or disable DAMON_LRU_SORT (default: disabled)");
30240e983ccSSeongJae Park 
damon_lru_sort_handle_commit_inputs(void)30340e983ccSSeongJae Park static int damon_lru_sort_handle_commit_inputs(void)
30440e983ccSSeongJae Park {
30540e983ccSSeongJae Park 	int err;
30640e983ccSSeongJae Park 
30740e983ccSSeongJae Park 	if (!commit_inputs)
30840e983ccSSeongJae Park 		return 0;
30940e983ccSSeongJae Park 
31040e983ccSSeongJae Park 	err = damon_lru_sort_apply_parameters();
31140e983ccSSeongJae Park 	commit_inputs = false;
31240e983ccSSeongJae Park 	return err;
31340e983ccSSeongJae Park }
31440e983ccSSeongJae Park 
damon_lru_sort_after_aggregation(struct damon_ctx * c)31540e983ccSSeongJae Park static int damon_lru_sort_after_aggregation(struct damon_ctx *c)
31640e983ccSSeongJae Park {
31740e983ccSSeongJae Park 	struct damos *s;
31840e983ccSSeongJae Park 
31940e983ccSSeongJae Park 	/* update the stats parameter */
32040e983ccSSeongJae Park 	damon_for_each_scheme(s, c) {
321dd172fbfSSeongJae Park 		if (s->action == DAMOS_LRU_PRIO)
322dd172fbfSSeongJae Park 			damon_lru_sort_hot_stat = s->stat;
323dd172fbfSSeongJae Park 		else if (s->action == DAMOS_LRU_DEPRIO)
324dd172fbfSSeongJae Park 			damon_lru_sort_cold_stat = s->stat;
32540e983ccSSeongJae Park 	}
32640e983ccSSeongJae Park 
32740e983ccSSeongJae Park 	return damon_lru_sort_handle_commit_inputs();
32840e983ccSSeongJae Park }
32940e983ccSSeongJae Park 
damon_lru_sort_after_wmarks_check(struct damon_ctx * c)33040e983ccSSeongJae Park static int damon_lru_sort_after_wmarks_check(struct damon_ctx *c)
33140e983ccSSeongJae Park {
33240e983ccSSeongJae Park 	return damon_lru_sort_handle_commit_inputs();
33340e983ccSSeongJae Park }
33440e983ccSSeongJae Park 
damon_lru_sort_init(void)33540e983ccSSeongJae Park static int __init damon_lru_sort_init(void)
33640e983ccSSeongJae Park {
3377ae2c17fSSeongJae Park 	int err = damon_modules_new_paddr_ctx_target(&ctx, &target);
33840e983ccSSeongJae Park 
3397ae2c17fSSeongJae Park 	if (err)
3407ae2c17fSSeongJae Park 		return err;
34140e983ccSSeongJae Park 
34240e983ccSSeongJae Park 	ctx->callback.after_wmarks_check = damon_lru_sort_after_wmarks_check;
34340e983ccSSeongJae Park 	ctx->callback.after_aggregation = damon_lru_sort_after_aggregation;
34440e983ccSSeongJae Park 
3457a034fbbSSeongJae Park 	/* 'enabled' has set before this function, probably via command line */
3467a034fbbSSeongJae Park 	if (enabled)
3477a034fbbSSeongJae Park 		err = damon_lru_sort_turn(true);
34840e983ccSSeongJae Park 
3497a034fbbSSeongJae Park 	return err;
35040e983ccSSeongJae Park }
35140e983ccSSeongJae Park 
35240e983ccSSeongJae Park module_init(damon_lru_sort_init);
353