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/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: 4d4e41b68299 ("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>

authored by

SeongJae Park and committed by
Andrew Morton
7d6fa31a 854f2764

+43 -6
+43 -6
mm/damon/sysfs-schemes.c
··· 139 139 * damon_sysfs_before_damos_apply() understands the situation by showing the 140 140 * 'finished' status and do nothing. 141 141 * 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 + * 142 149 * Finally, the tried regions request handling finisher function 143 150 * (damon_sysfs_schemes_update_regions_stop()) unregisters the callbacks. 144 151 */ ··· 161 154 int nr_regions; 162 155 unsigned long total_bytes; 163 156 enum damos_sysfs_regions_upd_status upd_status; 157 + unsigned long upd_timeout_jiffies; 164 158 }; 165 159 166 160 static struct damon_sysfs_scheme_regions * ··· 1862 1854 for (i = 0; i < sysfs_schemes->nr; i++) { 1863 1855 sysfs_regions = sysfs_schemes->schemes_arr[i]->tried_regions; 1864 1856 if (sysfs_regions->upd_status == 1865 - DAMOS_TRIED_REGIONS_UPD_STARTED) 1857 + DAMOS_TRIED_REGIONS_UPD_STARTED || 1858 + time_after(jiffies, 1859 + sysfs_regions->upd_timeout_jiffies)) 1866 1860 sysfs_regions->upd_status = 1867 1861 DAMOS_TRIED_REGIONS_UPD_FINISHED; 1868 1862 } ··· 1895 1885 return 0; 1896 1886 } 1897 1887 1888 + static struct damos *damos_sysfs_nth_scheme(int n, struct damon_ctx *ctx) 1889 + { 1890 + struct damos *scheme; 1891 + int i = 0; 1892 + 1893 + damon_for_each_scheme(scheme, ctx) { 1894 + if (i == n) 1895 + return scheme; 1896 + i++; 1897 + } 1898 + return NULL; 1899 + } 1900 + 1898 1901 static void damos_tried_regions_init_upd_status( 1899 - struct damon_sysfs_schemes *sysfs_schemes) 1902 + struct damon_sysfs_schemes *sysfs_schemes, 1903 + struct damon_ctx *ctx) 1900 1904 { 1901 1905 int i; 1906 + struct damos *scheme; 1907 + struct damon_sysfs_scheme_regions *sysfs_regions; 1902 1908 1903 - for (i = 0; i < sysfs_schemes->nr; i++) 1904 - sysfs_schemes->schemes_arr[i]->tried_regions->upd_status = 1905 - DAMOS_TRIED_REGIONS_UPD_IDLE; 1909 + for (i = 0; i < sysfs_schemes->nr; i++) { 1910 + sysfs_regions = sysfs_schemes->schemes_arr[i]->tried_regions; 1911 + scheme = damos_sysfs_nth_scheme(i, ctx); 1912 + if (!scheme) { 1913 + sysfs_regions->upd_status = 1914 + DAMOS_TRIED_REGIONS_UPD_FINISHED; 1915 + continue; 1916 + } 1917 + sysfs_regions->upd_status = DAMOS_TRIED_REGIONS_UPD_IDLE; 1918 + sysfs_regions->upd_timeout_jiffies = jiffies + 1919 + 2 * usecs_to_jiffies(scheme->apply_interval_us ? 1920 + scheme->apply_interval_us : 1921 + ctx->attrs.sample_interval); 1922 + } 1906 1923 } 1907 1924 1908 1925 /* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */ ··· 1939 1902 { 1940 1903 damon_sysfs_schemes_clear_regions(sysfs_schemes, ctx); 1941 1904 damon_sysfs_schemes_for_damos_callback = sysfs_schemes; 1942 - damos_tried_regions_init_upd_status(sysfs_schemes); 1905 + damos_tried_regions_init_upd_status(sysfs_schemes, ctx); 1943 1906 damos_regions_upd_total_bytes_only = total_bytes_only; 1944 1907 ctx->callback.before_damos_apply = damon_sysfs_before_damos_apply; 1945 1908 ctx->callback.after_sampling = damon_sysfs_after_sampling;