mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-26 12:26:11 +00:00
mm/damon/sysfs-schemes: add timeout for update_schemes_tried_regions
If a scheme is set to not applied to any monitoring target region for any
reasons including the target access pattern, quota, filters, or
watermarks, writing 'update_schemes_tried_regions' to 'state' DAMON sysfs
file can indefinitely hang. Fix the case by implementing a timeout for
the operation. The time limit is two apply intervals of each scheme.
Link: https://lkml.kernel.org/r/20231124213840.39157-1-sj@kernel.org
Fixes: 4d4e41b682
("mm/damon/sysfs-schemes: do not update tried regions more than one DAMON snapshot")
Signed-off-by: SeongJae Park <sj@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
854f2764b5
commit
7d6fa31a2f
1 changed files with 43 additions and 6 deletions
|
@ -139,6 +139,13 @@ static const struct kobj_type damon_sysfs_scheme_region_ktype = {
|
||||||
* damon_sysfs_before_damos_apply() understands the situation by showing the
|
* damon_sysfs_before_damos_apply() understands the situation by showing the
|
||||||
* 'finished' status and do nothing.
|
* 'finished' status and do nothing.
|
||||||
*
|
*
|
||||||
|
* If DAMOS is not applied to any region due to any reasons including the
|
||||||
|
* access pattern, the watermarks, the quotas, and the filters,
|
||||||
|
* ->before_damos_apply() will not be called back. Until the situation is
|
||||||
|
* changed, the update will not be finished. To avoid this,
|
||||||
|
* damon_sysfs_after_sampling() set the status as 'finished' if more than two
|
||||||
|
* apply intervals of the scheme is passed while the state is 'idle'.
|
||||||
|
*
|
||||||
* Finally, the tried regions request handling finisher function
|
* Finally, the tried regions request handling finisher function
|
||||||
* (damon_sysfs_schemes_update_regions_stop()) unregisters the callbacks.
|
* (damon_sysfs_schemes_update_regions_stop()) unregisters the callbacks.
|
||||||
*/
|
*/
|
||||||
|
@ -154,6 +161,7 @@ struct damon_sysfs_scheme_regions {
|
||||||
int nr_regions;
|
int nr_regions;
|
||||||
unsigned long total_bytes;
|
unsigned long total_bytes;
|
||||||
enum damos_sysfs_regions_upd_status upd_status;
|
enum damos_sysfs_regions_upd_status upd_status;
|
||||||
|
unsigned long upd_timeout_jiffies;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct damon_sysfs_scheme_regions *
|
static struct damon_sysfs_scheme_regions *
|
||||||
|
@ -1854,7 +1862,9 @@ static int damon_sysfs_after_sampling(struct damon_ctx *ctx)
|
||||||
for (i = 0; i < sysfs_schemes->nr; i++) {
|
for (i = 0; i < sysfs_schemes->nr; i++) {
|
||||||
sysfs_regions = sysfs_schemes->schemes_arr[i]->tried_regions;
|
sysfs_regions = sysfs_schemes->schemes_arr[i]->tried_regions;
|
||||||
if (sysfs_regions->upd_status ==
|
if (sysfs_regions->upd_status ==
|
||||||
DAMOS_TRIED_REGIONS_UPD_STARTED)
|
DAMOS_TRIED_REGIONS_UPD_STARTED ||
|
||||||
|
time_after(jiffies,
|
||||||
|
sysfs_regions->upd_timeout_jiffies))
|
||||||
sysfs_regions->upd_status =
|
sysfs_regions->upd_status =
|
||||||
DAMOS_TRIED_REGIONS_UPD_FINISHED;
|
DAMOS_TRIED_REGIONS_UPD_FINISHED;
|
||||||
}
|
}
|
||||||
|
@ -1885,14 +1895,41 @@ int damon_sysfs_schemes_clear_regions(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct damos *damos_sysfs_nth_scheme(int n, struct damon_ctx *ctx)
|
||||||
|
{
|
||||||
|
struct damos *scheme;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
damon_for_each_scheme(scheme, ctx) {
|
||||||
|
if (i == n)
|
||||||
|
return scheme;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void damos_tried_regions_init_upd_status(
|
static void damos_tried_regions_init_upd_status(
|
||||||
struct damon_sysfs_schemes *sysfs_schemes)
|
struct damon_sysfs_schemes *sysfs_schemes,
|
||||||
|
struct damon_ctx *ctx)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
struct damos *scheme;
|
||||||
|
struct damon_sysfs_scheme_regions *sysfs_regions;
|
||||||
|
|
||||||
for (i = 0; i < sysfs_schemes->nr; i++)
|
for (i = 0; i < sysfs_schemes->nr; i++) {
|
||||||
sysfs_schemes->schemes_arr[i]->tried_regions->upd_status =
|
sysfs_regions = sysfs_schemes->schemes_arr[i]->tried_regions;
|
||||||
DAMOS_TRIED_REGIONS_UPD_IDLE;
|
scheme = damos_sysfs_nth_scheme(i, ctx);
|
||||||
|
if (!scheme) {
|
||||||
|
sysfs_regions->upd_status =
|
||||||
|
DAMOS_TRIED_REGIONS_UPD_FINISHED;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sysfs_regions->upd_status = DAMOS_TRIED_REGIONS_UPD_IDLE;
|
||||||
|
sysfs_regions->upd_timeout_jiffies = jiffies +
|
||||||
|
2 * usecs_to_jiffies(scheme->apply_interval_us ?
|
||||||
|
scheme->apply_interval_us :
|
||||||
|
ctx->attrs.sample_interval);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */
|
/* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */
|
||||||
|
@ -1902,7 +1939,7 @@ int damon_sysfs_schemes_update_regions_start(
|
||||||
{
|
{
|
||||||
damon_sysfs_schemes_clear_regions(sysfs_schemes, ctx);
|
damon_sysfs_schemes_clear_regions(sysfs_schemes, ctx);
|
||||||
damon_sysfs_schemes_for_damos_callback = sysfs_schemes;
|
damon_sysfs_schemes_for_damos_callback = sysfs_schemes;
|
||||||
damos_tried_regions_init_upd_status(sysfs_schemes);
|
damos_tried_regions_init_upd_status(sysfs_schemes, ctx);
|
||||||
damos_regions_upd_total_bytes_only = total_bytes_only;
|
damos_regions_upd_total_bytes_only = total_bytes_only;
|
||||||
ctx->callback.before_damos_apply = damon_sysfs_before_damos_apply;
|
ctx->callback.before_damos_apply = damon_sysfs_before_damos_apply;
|
||||||
ctx->callback.after_sampling = damon_sysfs_after_sampling;
|
ctx->callback.after_sampling = damon_sysfs_after_sampling;
|
||||||
|
|
Loading…
Reference in a new issue