Skip to content

Commit 7d6fa31

Browse files
sjp38akpm00
authored andcommitted
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: 4d4e41b ("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>
1 parent 854f276 commit 7d6fa31

1 file changed

Lines changed: 43 additions & 6 deletions

File tree

mm/damon/sysfs-schemes.c

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,13 @@ static const struct kobj_type damon_sysfs_scheme_region_ktype = {
139139
* damon_sysfs_before_damos_apply() understands the situation by showing the
140140
* 'finished' status and do nothing.
141141
*
142+
* If DAMOS is not applied to any region due to any reasons including the
143+
* access pattern, the watermarks, the quotas, and the filters,
144+
* ->before_damos_apply() will not be called back. Until the situation is
145+
* changed, the update will not be finished. To avoid this,
146+
* damon_sysfs_after_sampling() set the status as 'finished' if more than two
147+
* apply intervals of the scheme is passed while the state is 'idle'.
148+
*
142149
* Finally, the tried regions request handling finisher function
143150
* (damon_sysfs_schemes_update_regions_stop()) unregisters the callbacks.
144151
*/
@@ -154,6 +161,7 @@ struct damon_sysfs_scheme_regions {
154161
int nr_regions;
155162
unsigned long total_bytes;
156163
enum damos_sysfs_regions_upd_status upd_status;
164+
unsigned long upd_timeout_jiffies;
157165
};
158166

159167
static struct damon_sysfs_scheme_regions *
@@ -1854,7 +1862,9 @@ static int damon_sysfs_after_sampling(struct damon_ctx *ctx)
18541862
for (i = 0; i < sysfs_schemes->nr; i++) {
18551863
sysfs_regions = sysfs_schemes->schemes_arr[i]->tried_regions;
18561864
if (sysfs_regions->upd_status ==
1857-
DAMOS_TRIED_REGIONS_UPD_STARTED)
1865+
DAMOS_TRIED_REGIONS_UPD_STARTED ||
1866+
time_after(jiffies,
1867+
sysfs_regions->upd_timeout_jiffies))
18581868
sysfs_regions->upd_status =
18591869
DAMOS_TRIED_REGIONS_UPD_FINISHED;
18601870
}
@@ -1885,14 +1895,41 @@ int damon_sysfs_schemes_clear_regions(
18851895
return 0;
18861896
}
18871897

1898+
static struct damos *damos_sysfs_nth_scheme(int n, struct damon_ctx *ctx)
1899+
{
1900+
struct damos *scheme;
1901+
int i = 0;
1902+
1903+
damon_for_each_scheme(scheme, ctx) {
1904+
if (i == n)
1905+
return scheme;
1906+
i++;
1907+
}
1908+
return NULL;
1909+
}
1910+
18881911
static void damos_tried_regions_init_upd_status(
1889-
struct damon_sysfs_schemes *sysfs_schemes)
1912+
struct damon_sysfs_schemes *sysfs_schemes,
1913+
struct damon_ctx *ctx)
18901914
{
18911915
int i;
1916+
struct damos *scheme;
1917+
struct damon_sysfs_scheme_regions *sysfs_regions;
18921918

1893-
for (i = 0; i < sysfs_schemes->nr; i++)
1894-
sysfs_schemes->schemes_arr[i]->tried_regions->upd_status =
1895-
DAMOS_TRIED_REGIONS_UPD_IDLE;
1919+
for (i = 0; i < sysfs_schemes->nr; i++) {
1920+
sysfs_regions = sysfs_schemes->schemes_arr[i]->tried_regions;
1921+
scheme = damos_sysfs_nth_scheme(i, ctx);
1922+
if (!scheme) {
1923+
sysfs_regions->upd_status =
1924+
DAMOS_TRIED_REGIONS_UPD_FINISHED;
1925+
continue;
1926+
}
1927+
sysfs_regions->upd_status = DAMOS_TRIED_REGIONS_UPD_IDLE;
1928+
sysfs_regions->upd_timeout_jiffies = jiffies +
1929+
2 * usecs_to_jiffies(scheme->apply_interval_us ?
1930+
scheme->apply_interval_us :
1931+
ctx->attrs.sample_interval);
1932+
}
18961933
}
18971934

18981935
/* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */
@@ -1902,7 +1939,7 @@ int damon_sysfs_schemes_update_regions_start(
19021939
{
19031940
damon_sysfs_schemes_clear_regions(sysfs_schemes, ctx);
19041941
damon_sysfs_schemes_for_damos_callback = sysfs_schemes;
1905-
damos_tried_regions_init_upd_status(sysfs_schemes);
1942+
damos_tried_regions_init_upd_status(sysfs_schemes, ctx);
19061943
damos_regions_upd_total_bytes_only = total_bytes_only;
19071944
ctx->callback.before_damos_apply = damon_sysfs_before_damos_apply;
19081945
ctx->callback.after_sampling = damon_sysfs_after_sampling;

0 commit comments

Comments
 (0)