diff options
Diffstat (limited to 'mm')
| -rw-r--r-- | mm/damon/core.c | 77 |
1 files changed, 72 insertions, 5 deletions
diff --git a/mm/damon/core.c b/mm/damon/core.c index 05e4bef367dbf..980a31cd3498e 100644 --- a/mm/damon/core.c +++ b/mm/damon/core.c @@ -3328,14 +3328,20 @@ done: return 0; } -static int walk_system_ram(struct resource *res, void *arg) +struct damon_system_ram_range_walk_arg { + bool walked; + struct resource res; +}; + +static int damon_system_ram_walk_fn(struct resource *res, void *arg) { - struct resource *a = arg; + struct damon_system_ram_range_walk_arg *a = arg; - if (resource_size(a) < resource_size(res)) { - a->start = res->start; - a->end = res->end; + if (!a->walked) { + a->walked = true; + a->res.start = res->start; } + a->res.end = res->end; return 0; } @@ -3352,6 +3358,67 @@ static unsigned long damon_res_to_core_addr(resource_size_t ra, return ra / addr_unit; } +static bool damon_find_system_rams_range(unsigned long *start, + unsigned long *end, unsigned long addr_unit) +{ + struct damon_system_ram_range_walk_arg arg = {}; + + walk_system_ram_res(0, -1, &arg, damon_system_ram_walk_fn); + if (!arg.walked) + return false; + *start = damon_res_to_core_addr(arg.res.start, addr_unit); + *end = damon_res_to_core_addr(arg.res.end + 1, addr_unit); + if (*end <= *start) + return false; + return true; +} + +/** + * damon_set_region_system_rams_default() - Set the region of the given + * monitoring target as requested, or to cover all 'System RAM' resources. + * @t: The monitoring target to set the region. + * @start: The pointer to the start address of the region. + * @end: The pointer to the end address of the region. + * @addr_unit: The address unit for the damon_ctx of @t. + * @min_region_sz: Minimum region size. + * + * This function sets the region of @t as requested by @start and @end. If the + * values of @start and @end are zero, however, this function finds 'System + * RAM' resources and sets the region to cover all the resource. In the latter + * case, this function saves the start and the end addresseses of the first and + * the last resources in @start and @end, respectively. + * + * Return: 0 on success, negative error code otherwise. + */ +int damon_set_region_system_rams_default(struct damon_target *t, + unsigned long *start, unsigned long *end, + unsigned long addr_unit, unsigned long min_region_sz) +{ + struct damon_addr_range addr_range; + + if (*start > *end) + return -EINVAL; + + if (!*start && !*end && + !damon_find_system_rams_range(start, end, addr_unit)) + return -EINVAL; + + addr_range.start = *start; + addr_range.end = *end; + return damon_set_regions(t, &addr_range, 1, min_region_sz); +} + +static int walk_system_ram(struct resource *res, void *arg) +{ + struct resource *a = arg; + + if (resource_size(a) < resource_size(res)) { + a->start = res->start; + a->end = res->end; + } + return 0; +} + /* * Find biggest 'System RAM' resource and store its start and end address in * @start and @end, respectively. If no System RAM is found, returns false. |
