From nobody Fri Apr 19 06:21:32 2024 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 54F0BC43219 for ; Thu, 24 Nov 2022 21:21:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229682AbiKXVVf (ORCPT ); Thu, 24 Nov 2022 16:21:35 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53278 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229581AbiKXVVX (ORCPT ); Thu, 24 Nov 2022 16:21:23 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9A98293CF7 for ; Thu, 24 Nov 2022 13:21:22 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 59CB3B82905 for ; Thu, 24 Nov 2022 21:21:21 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8DDB0C433B5; Thu, 24 Nov 2022 21:21:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1669324880; bh=YFde7Cg3Hj4Ke5ExGefyiTVasYPENA1m1IEZnM/nGhM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Gl6EnRqJBxFjy18Iah9VqcR0bmZ1Jn/wwqzkIsrbgqDx/IfCPgTt5d9a94tbDkXFD 60k1/8ZNp/Fkiw63+YfOHXZ7Xj55J6NotdbVC9PyEiWAsI1JwE25fT9AxNm1lekOr0 vEMatfZS+8MRHgx/BkTGNHINHRcbDf/sLiI9w3F0MXtYND2uDCttF/8KFLaVgbRufU tzFfvm9f8yrvTC1sB6FcSMkgjooYlbTwwh4imj/W+Dd348xuySRGnTvlSuU9f72346 Rn/16RrolIPWiQ6RK2b9fxuiskaDMxnknY9Fq32EfifYbqCFzJTCG2gFLevrp7IXai 6wlagUCiBncwQ== From: SeongJae Park To: Andrew Morton Cc: damon@lists.linux.dev, linux-mm@kvack.org, linux-kernel@vger.kernel.org, SeongJae Park Subject: [RFC PATCH 01/11] mm/damon/core: implement damos filter Date: Thu, 24 Nov 2022 21:21:04 +0000 Message-Id: <20221124212114.136863-2-sj@kernel.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20221124212114.136863-1-sj@kernel.org> References: <20221124212114.136863-1-sj@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" DAMOS let users do system operation in a data access pattern oriented way. The data access pattern, which is extracted by DAMON, is somewhat accurate more than what user space could know in many cases. However, in some situation, users could know something more than the kernel about the pattern or some special requirements for some types of memory or processes. For example, some users would have slow swap devices and knows latency-ciritical processes and therefore want to use DAMON-based proactive reclamation (DAMON_RECLAIM) for only non-anonymous pages of non-latency-critical processes. For such restriction, users could exclude the memory regions from the initial monitoring regions and use non-dynamic monitoring regions update monitoring operations set including fvaddr and paddr. They could also adjust the DAMOS target access pattern. For dynamically changing memory layout and access pattern, those would be not enough. To help the case, add an interface, namely DAMOS filters, which can be used to avoid the DAMOS actions be applied to specific types of memory, to DAMON kernel API (damon.h). At the moment, it supports filtering anonymous pages and/or specific memory cgroups in or out for each DAMOS scheme. Note that this commit adds only the interface to the DAMON kernel API. The impelmentation should be made in the monitoring operations sets, and following commits will add that. Signed-off-by: SeongJae Park --- include/linux/damon.h | 51 +++++++++++++++++++++++++++++++++++++++++++ mm/damon/core.c | 39 +++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/include/linux/damon.h b/include/linux/damon.h index 35630634d790..42cea3bf7319 100644 --- a/include/linux/damon.h +++ b/include/linux/damon.h @@ -8,6 +8,7 @@ #ifndef _DAMON_H_ #define _DAMON_H_ =20 +#include #include #include #include @@ -215,6 +216,39 @@ struct damos_stat { unsigned long qt_exceeds; }; =20 +/** + * enum damos_filter_type - Type of memory for &struct damos_filter + * @DAMOS_FILTER_TYPE_ANON: Anonymous pages. + * @DAMOS_FILTER_TYPE_MEMCG: Specific memcg's pages. + * @NR_DAMOS_FILTER_TYPES: Number of filter types. + */ +enum damos_filter_type { + DAMOS_FILTER_TYPE_ANON, + DAMOS_FILTER_TYPE_MEMCG, + NR_DAMOS_FILTER_TYPES, +}; + +/** + * struct damos_filter - DAMOS action target memory filter. + * @type: Type of the page. + * @matching: If the matching page should filtered out or in. + * @memcg_id: Memcg id of the question if @type is DAMOS_FILTER_MEMCG. + * @list: List head for siblings. + * + * Before applying the &damos->action to a memory region, DAMOS checks if = each + * page of the region matches to this and avoid applying the action if so. + * Note that the check support is up to &struct damon_operations + * implementation. + */ +struct damos_filter { + enum damos_filter_type type; + bool matching; + union { + unsigned short memcg_id; + }; + struct list_head list; +}; + /** * struct damos_access_pattern - Target access pattern of the given scheme. * @min_sz_region: Minimum size of target regions. @@ -239,6 +273,7 @@ struct damos_access_pattern { * @action: &damo_action to be applied to the target regions. * @quota: Control the aggressiveness of this scheme. * @wmarks: Watermarks for automated (in)activation of this scheme. + * @filters: Additional set of &struct damos_filter for &action. * @stat: Statistics of this scheme. * @list: List head for siblings. * @@ -254,6 +289,10 @@ struct damos_access_pattern { * If all schemes that registered to a &struct damon_ctx are inactive, DAM= ON * stops monitoring and just repeatedly checks the watermarks. * + * Before applying the &action to a memory region, &struct damon_operations + * implementation could check pages of the region and skip &action to resp= ect + * &filters + * * After applying the &action to each region, &stat_count and &stat_sz is * updated to reflect the number of regions and total size of regions that= the * &action is applied. @@ -263,6 +302,7 @@ struct damos { enum damos_action action; struct damos_quota quota; struct damos_watermarks wmarks; + struct list_head filters; struct damos_stat stat; struct list_head list; }; @@ -516,6 +556,12 @@ static inline unsigned long damon_sz_region(struct dam= on_region *r) #define damon_for_each_scheme_safe(s, next, ctx) \ list_for_each_entry_safe(s, next, &(ctx)->schemes, list) =20 +#define damos_for_each_filter(f, scheme) \ + list_for_each_entry(f, &(scheme)->filters, list) + +#define damos_for_each_filter_safe(f, next, scheme) \ + list_for_each_entry_safe(f, next, &(scheme)->filters, list) + #ifdef CONFIG_DAMON =20 struct damon_region *damon_new_region(unsigned long start, unsigned long e= nd); @@ -536,6 +582,11 @@ void damon_destroy_region(struct damon_region *r, stru= ct damon_target *t); int damon_set_regions(struct damon_target *t, struct damon_addr_range *ran= ges, unsigned int nr_ranges); =20 +struct damos_filter *damos_new_filter(enum damos_filter_type type, + bool matching); +void damos_add_filter(struct damos *s, struct damos_filter *f); +void damos_destroy_filter(struct damos_filter *f); + struct damos *damon_new_scheme(struct damos_access_pattern *pattern, enum damos_action action, struct damos_quota *quota, struct damos_watermarks *wmarks); diff --git a/mm/damon/core.c b/mm/damon/core.c index 9cbcc143179e..d924657ad622 100644 --- a/mm/damon/core.c +++ b/mm/damon/core.c @@ -273,6 +273,40 @@ int damon_set_regions(struct damon_target *t, struct d= amon_addr_range *ranges, return 0; } =20 +struct damos_filter *damos_new_filter(enum damos_filter_type type, + bool matching) +{ + struct damos_filter *filter; + + filter =3D kmalloc(sizeof(*filter), GFP_KERNEL); + if (!filter) + return NULL; + filter->type =3D type; + filter->matching =3D matching; + return filter; +} + +void damos_add_filter(struct damos *s, struct damos_filter *f) +{ + list_add_tail(&f->list, &s->filters); +} + +static void damos_del_filter(struct damos_filter *f) +{ + list_del(&f->list); +} + +static void damos_free_filter(struct damos_filter *f) +{ + kfree(f); +} + +void damos_destroy_filter(struct damos_filter *f) +{ + damos_del_filter(f); + damos_free_filter(f); +} + /* initialize private fields of damos_quota and return the pointer */ static struct damos_quota *damos_quota_init_priv(struct damos_quota *quota) { @@ -297,6 +331,7 @@ struct damos *damon_new_scheme(struct damos_access_patt= ern *pattern, return NULL; scheme->pattern =3D *pattern; scheme->action =3D action; + INIT_LIST_HEAD(&scheme->filters); scheme->stat =3D (struct damos_stat){}; INIT_LIST_HEAD(&scheme->list); =20 @@ -325,6 +360,10 @@ static void damon_free_scheme(struct damos *s) =20 void damon_destroy_scheme(struct damos *s) { + struct damos_filter *f, *next; + + damos_for_each_filter_safe(f, next, s) + damos_destroy_filter(f); damon_del_scheme(s); damon_free_scheme(s); } --=20 2.25.1