From patchwork Wed Mar 18 11:27:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: SeongJae Park X-Patchwork-Id: 11445001 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C817914DD for ; Wed, 18 Mar 2020 11:29:03 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 9549C20771 for ; Wed, 18 Mar 2020 11:29:03 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=amazon.com header.i=@amazon.com header.b="AJXsCP1B" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 9549C20771 Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=amazon.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id D71A06B0006; Wed, 18 Mar 2020 07:29:02 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id D215F6B000D; Wed, 18 Mar 2020 07:29:02 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id BE9D06B0010; Wed, 18 Mar 2020 07:29:02 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0085.hostedemail.com [216.40.44.85]) by kanga.kvack.org (Postfix) with ESMTP id A31E46B0006 for ; Wed, 18 Mar 2020 07:29:02 -0400 (EDT) Received: from smtpin08.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay04.hostedemail.com (Postfix) with ESMTP id 5604B45AA for ; Wed, 18 Mar 2020 11:29:02 +0000 (UTC) X-FDA: 76608261324.08.route34_891317941345e X-Spam-Summary: 1,0,0,,d41d8cd98f00b204,prvs=339ded45b=sjpark@amazon.com,,RULES_HIT:30054:30064,0,RBL:207.171.190.10:@amazon.com:.lbl8.mailshell.net-62.18.0.100 66.10.201.10,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:fp,MSBL:0,DNSBL:neutral,Custom_rules:0:0:0,LFtime:23,LUA_SUMMARY:none X-HE-Tag: route34_891317941345e X-Filterd-Recvd-Size: 4266 Received: from smtp-fw-33001.amazon.com (smtp-fw-33001.amazon.com [207.171.190.10]) by imf36.hostedemail.com (Postfix) with ESMTP for ; Wed, 18 Mar 2020 11:29:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1584530942; x=1616066942; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=KKbmZdP/bzj7xd/Z96OBTjD6dd06R7k1zcFdO8AZExk=; b=AJXsCP1BGpZ2ImwD481Ygp0deAVDN+5+Z8SH2FSVqfEbftwLEhMvk6uK nd3Y2q0K/5dgS+vnNXJD6v44J/cTf6oQCQ4k4X9M5pgMG89STMB7TkYab s4Crrejur0kl6stVVilCZKdpDVE3hsyRu+ZntNaG9usra8UUUy3mAntlK Y=; IronPort-SDR: xjowkPUio85p7GWo8Oy3Acibo9IimbZbB35/t95QZvh9iYFFj2F/VmMxSpdnXQFohKKPmDe6kM xHHpuHD+egXg== X-IronPort-AV: E=Sophos;i="5.70,567,1574121600"; d="scan'208";a="33270648" Received: from sea32-co-svc-lb4-vlan3.sea.corp.amazon.com (HELO email-inbound-relay-1a-e34f1ddc.us-east-1.amazon.com) ([10.47.23.38]) by smtp-border-fw-out-33001.sea14.amazon.com with ESMTP; 18 Mar 2020 11:28:57 +0000 Received: from EX13MTAUEA002.ant.amazon.com (iad55-ws-svc-p15-lb9-vlan2.iad.amazon.com [10.40.159.162]) by email-inbound-relay-1a-e34f1ddc.us-east-1.amazon.com (Postfix) with ESMTPS id D0378A2CD1; Wed, 18 Mar 2020 11:28:46 +0000 (UTC) Received: from EX13D31EUA001.ant.amazon.com (10.43.165.15) by EX13MTAUEA002.ant.amazon.com (10.43.61.77) with Microsoft SMTP Server (TLS) id 15.0.1236.3; Wed, 18 Mar 2020 11:28:46 +0000 Received: from u886c93fd17d25d.ant.amazon.com (10.43.161.235) by EX13D31EUA001.ant.amazon.com (10.43.165.15) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Wed, 18 Mar 2020 11:28:25 +0000 From: SeongJae Park To: CC: SeongJae Park , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH v7 01/15] scripts/spelling: Add a few more typos Date: Wed, 18 Mar 2020 12:27:08 +0100 Message-ID: <20200318112722.30143-2-sjpark@amazon.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200318112722.30143-1-sjpark@amazon.com> References: <20200318112722.30143-1-sjpark@amazon.com> MIME-Version: 1.0 X-Originating-IP: [10.43.161.235] X-ClientProxiedBy: EX13D28UWC001.ant.amazon.com (10.43.162.166) To EX13D31EUA001.ant.amazon.com (10.43.165.15) X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: From: SeongJae Park This commit adds typos found from DAMON patchset. Signed-off-by: SeongJae Park --- scripts/spelling.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/spelling.txt b/scripts/spelling.txt index 672b5931bc8d..2fcad5dbd9c6 100644 --- a/scripts/spelling.txt +++ b/scripts/spelling.txt @@ -57,6 +57,7 @@ actualy||actually acumulating||accumulating acumulative||accumulative acumulator||accumulator +acutally||actually adapater||adapter addional||additional additionaly||additionally @@ -241,6 +242,7 @@ calender||calendar calescing||coalescing calle||called callibration||calibration +callser||caller calucate||calculate calulate||calculate cancelation||cancellation @@ -988,6 +990,7 @@ partiton||partition pased||passed passin||passing pathes||paths +pattrns||patterns pecularities||peculiarities peformance||performance peforming||performing @@ -1338,6 +1341,7 @@ thead||thread therfore||therefore thier||their threds||threads +threee||three threshhold||threshold thresold||threshold throught||through From patchwork Wed Mar 18 11:27:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: SeongJae Park X-Patchwork-Id: 11445003 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8872E6CA for ; Wed, 18 Mar 2020 11:29:35 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 46FB220781 for ; Wed, 18 Mar 2020 11:29:35 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=amazon.com header.i=@amazon.com header.b="emotM0fE" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 46FB220781 Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=amazon.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 819716B000D; Wed, 18 Mar 2020 07:29:34 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 7A2D66B0010; Wed, 18 Mar 2020 07:29:34 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 691D26B0037; Wed, 18 Mar 2020 07:29:34 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0254.hostedemail.com [216.40.44.254]) by kanga.kvack.org (Postfix) with ESMTP id 514676B000D for ; Wed, 18 Mar 2020 07:29:34 -0400 (EDT) Received: from smtpin01.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay04.hostedemail.com (Postfix) with ESMTP id F27E72472 for ; Wed, 18 Mar 2020 11:29:33 +0000 (UTC) X-FDA: 76608262668.01.dress61_8dab543e6f73d X-Spam-Summary: 1,0,0,,d41d8cd98f00b204,prvs=339ded45b=sjpark@amazon.com,,RULES_HIT:30054:30064,0,RBL:207.171.184.25:@amazon.com:.lbl8.mailshell.net-66.10.201.10 62.18.0.100,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:fp,MSBL:0,DNSBL:neutral,Custom_rules:0:0:0,LFtime:23,LUA_SUMMARY:none X-HE-Tag: dress61_8dab543e6f73d X-Filterd-Recvd-Size: 3753 Received: from smtp-fw-9101.amazon.com (smtp-fw-9101.amazon.com [207.171.184.25]) by imf42.hostedemail.com (Postfix) with ESMTP for ; Wed, 18 Mar 2020 11:29:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1584530974; x=1616066974; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=JA2aQZlnEaxp5yQP3+f4dvGiPHN9KB1VJHGZIRRVqdU=; b=emotM0fEpWD20Kl0e0fNzKwG/jzfXLpOe789xfMtdJzB/ALXRd/12RZk 7Lbrve1JlVVyZ3TLPtjnpuNE3N/XSVhGfESIGacNS8B/8SOEknsgW6lV4 xv7GLnylLIzzX7VZp2IVub96EUXdvRy1Mc+5NSfQbtTX7+wt3furtvBzY s=; IronPort-SDR: BtpZ7YY1oweq6otGrrEHR3D6EGguH0I4AXG6xgXP9yMfDd/uvcf+ez/206DLaM/RhbLjw8458a KR2kLOxxhc9g== X-IronPort-AV: E=Sophos;i="5.70,567,1574121600"; d="scan'208";a="23517231" Received: from sea32-co-svc-lb4-vlan3.sea.corp.amazon.com (HELO email-inbound-relay-1a-821c648d.us-east-1.amazon.com) ([10.47.23.38]) by smtp-border-fw-out-9101.sea19.amazon.com with ESMTP; 18 Mar 2020 11:29:29 +0000 Received: from EX13MTAUEA002.ant.amazon.com (iad55-ws-svc-p15-lb9-vlan3.iad.amazon.com [10.40.159.166]) by email-inbound-relay-1a-821c648d.us-east-1.amazon.com (Postfix) with ESMTPS id 094BBA29FC; Wed, 18 Mar 2020 11:29:18 +0000 (UTC) Received: from EX13D31EUA001.ant.amazon.com (10.43.165.15) by EX13MTAUEA002.ant.amazon.com (10.43.61.77) with Microsoft SMTP Server (TLS) id 15.0.1236.3; Wed, 18 Mar 2020 11:29:18 +0000 Received: from u886c93fd17d25d.ant.amazon.com (10.43.161.235) by EX13D31EUA001.ant.amazon.com (10.43.165.15) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Wed, 18 Mar 2020 11:29:01 +0000 From: SeongJae Park To: CC: SeongJae Park , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH v7 02/15] mm/page_ext: Export lookup_page_ext() to GPL modules Date: Wed, 18 Mar 2020 12:27:09 +0100 Message-ID: <20200318112722.30143-3-sjpark@amazon.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200318112722.30143-1-sjpark@amazon.com> References: <20200318112722.30143-1-sjpark@amazon.com> MIME-Version: 1.0 X-Originating-IP: [10.43.161.235] X-ClientProxiedBy: EX13D28UWC001.ant.amazon.com (10.43.162.166) To EX13D31EUA001.ant.amazon.com (10.43.165.15) X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: From: SeongJae Park This commit exports 'lookup_page_ext()' to GPL modules. This will be used by DAMON. This reverts commit a50179d0e22931032aa56718cd069b0ec74974c6. --- mm/page_ext.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mm/page_ext.c b/mm/page_ext.c index 4ade843ff588..71169b45bba9 100644 --- a/mm/page_ext.c +++ b/mm/page_ext.c @@ -131,6 +131,7 @@ struct page_ext *lookup_page_ext(const struct page *page) MAX_ORDER_NR_PAGES); return get_entry(base, index); } +EXPORT_SYMBOL_GPL(lookup_page_ext); static int __init alloc_node_page_ext(int nid) { From patchwork Wed Mar 18 11:27:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: SeongJae Park X-Patchwork-Id: 11445005 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 75C6F1392 for ; Wed, 18 Mar 2020 11:31:26 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 34C0620776 for ; Wed, 18 Mar 2020 11:31:26 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=amazon.com header.i=@amazon.com header.b="mYs33IE2" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 34C0620776 Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=amazon.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 6DEA86B0005; Wed, 18 Mar 2020 07:31:25 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 68FD46B0006; Wed, 18 Mar 2020 07:31:25 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 57E6E6B000D; Wed, 18 Mar 2020 07:31:25 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0238.hostedemail.com [216.40.44.238]) by kanga.kvack.org (Postfix) with ESMTP id 3C1DD6B0005 for ; Wed, 18 Mar 2020 07:31:25 -0400 (EDT) Received: from smtpin01.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay05.hostedemail.com (Postfix) with ESMTP id DB57B181AEF0B for ; Wed, 18 Mar 2020 11:31:24 +0000 (UTC) X-FDA: 76608267288.01.frame81_c3e7013d5857 X-Spam-Summary: 1,0,0,,d41d8cd98f00b204,prvs=339ded45b=sjpark@amazon.com,,RULES_HIT:2539:30003:30034:30054:30064:30067,0,RBL:207.171.184.25:@amazon.com:.lbl8.mailshell.net-62.18.0.100 66.10.201.10,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:fp,MSBL:0,DNSBL:neutral,Custom_rules:0:0:0,LFtime:233,LUA_SUMMARY:none X-HE-Tag: frame81_c3e7013d5857 X-Filterd-Recvd-Size: 10284 Received: from smtp-fw-9101.amazon.com (smtp-fw-9101.amazon.com [207.171.184.25]) by imf42.hostedemail.com (Postfix) with ESMTP for ; Wed, 18 Mar 2020 11:31:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1584531085; x=1616067085; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=Gz1TacAIoe7eEilKrgWA9QhMe33T33CzRWdxDRA3U50=; b=mYs33IE2VHtWoQ/LYEJEIMNMRB5NyzHwDFb8lBdVCR0XaqXFJIn4BzxJ 2jk0Ozi+qxW9uRza2iP4rkVLdq1Mg6eNNRp8zgUueysGmmoIKDh0KAOZ8 p1TvzEib8Gh1NXELZkIsHHuchzWuA3ttyj5rL4x3261eWKJF+MwWoWqjx w=; IronPort-SDR: s/i5SgHJv+MZoUH8Bxx5k4MF3WW0QocPzQAs0cJ79QDOq8+JW6UambIaoUQDmZo0kexIA2gVkP 105ZvVy9yzdg== X-IronPort-AV: E=Sophos;i="5.70,567,1574121600"; d="scan'208";a="23517497" Received: from sea32-co-svc-lb4-vlan3.sea.corp.amazon.com (HELO email-inbound-relay-1e-62350142.us-east-1.amazon.com) ([10.47.23.38]) by smtp-border-fw-out-9101.sea19.amazon.com with ESMTP; 18 Mar 2020 11:31:21 +0000 Received: from EX13MTAUEA002.ant.amazon.com (iad55-ws-svc-p15-lb9-vlan3.iad.amazon.com [10.40.159.166]) by email-inbound-relay-1e-62350142.us-east-1.amazon.com (Postfix) with ESMTPS id 11C07A2BC2; Wed, 18 Mar 2020 11:31:10 +0000 (UTC) Received: from EX13D31EUA001.ant.amazon.com (10.43.165.15) by EX13MTAUEA002.ant.amazon.com (10.43.61.77) with Microsoft SMTP Server (TLS) id 15.0.1236.3; Wed, 18 Mar 2020 11:31:10 +0000 Received: from u886c93fd17d25d.ant.amazon.com (10.43.161.235) by EX13D31EUA001.ant.amazon.com (10.43.165.15) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Wed, 18 Mar 2020 11:30:51 +0000 From: SeongJae Park To: CC: SeongJae Park , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH v7 03/15] mm: Introduce Data Access MONitor (DAMON) Date: Wed, 18 Mar 2020 12:27:10 +0100 Message-ID: <20200318112722.30143-4-sjpark@amazon.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200318112722.30143-1-sjpark@amazon.com> References: <20200318112722.30143-1-sjpark@amazon.com> MIME-Version: 1.0 X-Originating-IP: [10.43.161.235] X-ClientProxiedBy: EX13D28UWC001.ant.amazon.com (10.43.162.166) To EX13D31EUA001.ant.amazon.com (10.43.165.15) X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: From: SeongJae Park This commit introduces a kernel module named DAMON. Note that this commit is implementing only the stub for the module load/unload, basic data structures, and simple manipulation functions of the structures to keep the size of commit small. The core mechanisms of DAMON will be implemented one by one by following commits. Signed-off-by: SeongJae Park --- include/linux/damon.h | 38 +++++++++ mm/Kconfig | 11 +++ mm/Makefile | 1 + mm/damon.c | 189 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 239 insertions(+) create mode 100644 include/linux/damon.h create mode 100644 mm/damon.c diff --git a/include/linux/damon.h b/include/linux/damon.h new file mode 100644 index 000000000000..7117bb7e7544 --- /dev/null +++ b/include/linux/damon.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * DAMON api + * + * Copyright 2019 Amazon.com, Inc. or its affiliates. All rights reserved. + * + * Author: SeongJae Park + */ + +#ifndef _DAMON_H_ +#define _DAMON_H_ + +#include +#include + +/* Represents a monitoring target region on the virtual address space */ +struct damon_region { + unsigned long vm_start; + unsigned long vm_end; + unsigned long sampling_addr; + unsigned int nr_accesses; + struct list_head list; +}; + +/* Represents a monitoring target task */ +struct damon_task { + unsigned long pid; + struct list_head regions_list; + struct list_head list; +}; + +struct damon_ctx { + struct rnd_state rndseed; + + struct list_head tasks_list; /* 'damon_task' objects */ +}; + +#endif diff --git a/mm/Kconfig b/mm/Kconfig index ab80933be65f..79da00d15604 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -739,4 +739,15 @@ config ARCH_HAS_HUGEPD config MAPPING_DIRTY_HELPERS bool +config DAMON + tristate "Data Access Monitor" + depends on MMU + help + Provides data access monitoring. + + DAMON is a kernel module that allows users to monitor the actual + memory access pattern of specific user-space processes. It aims to + be 1) accurate enough to be useful for performance-centric domains, + and 2) sufficiently light-weight so that it can be applied online. + endmenu diff --git a/mm/Makefile b/mm/Makefile index 1937cc251883..2911b3832c90 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -108,3 +108,4 @@ obj-$(CONFIG_ZONE_DEVICE) += memremap.o obj-$(CONFIG_HMM_MIRROR) += hmm.o obj-$(CONFIG_MEMFD_CREATE) += memfd.o obj-$(CONFIG_MAPPING_DIRTY_HELPERS) += mapping_dirty_helpers.o +obj-$(CONFIG_DAMON) += damon.o diff --git a/mm/damon.c b/mm/damon.c new file mode 100644 index 000000000000..d7e6226ab7f1 --- /dev/null +++ b/mm/damon.c @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Data Access Monitor + * + * Copyright 2019 Amazon.com, Inc. or its affiliates. All rights reserved. + * + * Author: SeongJae Park + */ + +#define pr_fmt(fmt) "damon: " fmt + +#include +#include +#include +#include + +#define damon_get_task_struct(t) \ + (get_pid_task(find_vpid(t->pid), PIDTYPE_PID)) + +#define damon_next_region(r) \ + (container_of(r->list.next, struct damon_region, list)) + +#define damon_prev_region(r) \ + (container_of(r->list.prev, struct damon_region, list)) + +#define damon_for_each_region(r, t) \ + list_for_each_entry(r, &t->regions_list, list) + +#define damon_for_each_region_safe(r, next, t) \ + list_for_each_entry_safe(r, next, &t->regions_list, list) + +#define damon_for_each_task(ctx, t) \ + list_for_each_entry(t, &(ctx)->tasks_list, list) + +#define damon_for_each_task_safe(ctx, t, next) \ + list_for_each_entry_safe(t, next, &(ctx)->tasks_list, list) + +/* Get a random number in [l, r) */ +#define damon_rand(ctx, l, r) (l + prandom_u32_state(&ctx->rndseed) % (r - l)) + +/* + * Construct a damon_region struct + * + * Returns the pointer to the new struct if success, or NULL otherwise + */ +static struct damon_region *damon_new_region(struct damon_ctx *ctx, + unsigned long vm_start, unsigned long vm_end) +{ + struct damon_region *region; + + region = kmalloc(sizeof(*region), GFP_KERNEL); + if (!region) + return NULL; + + region->vm_start = vm_start; + region->vm_end = vm_end; + region->nr_accesses = 0; + region->sampling_addr = damon_rand(ctx, vm_start, vm_end); + INIT_LIST_HEAD(®ion->list); + + return region; +} + +/* + * Add a region between two other regions + */ +static inline void damon_insert_region(struct damon_region *r, + struct damon_region *prev, struct damon_region *next) +{ + __list_add(&r->list, &prev->list, &next->list); +} + +static void damon_add_region(struct damon_region *r, struct damon_task *t) +{ + list_add_tail(&r->list, &t->regions_list); +} + +static void damon_del_region(struct damon_region *r) +{ + list_del(&r->list); +} + +static void damon_free_region(struct damon_region *r) +{ + kfree(r); +} + +static void damon_destroy_region(struct damon_region *r) +{ + damon_del_region(r); + damon_free_region(r); +} + +/* + * Construct a damon_task struct + * + * Returns the pointer to the new struct if success, or NULL otherwise + */ +static struct damon_task *damon_new_task(unsigned long pid) +{ + struct damon_task *t; + + t = kmalloc(sizeof(*t), GFP_KERNEL); + if (!t) + return NULL; + + t->pid = pid; + INIT_LIST_HEAD(&t->regions_list); + + return t; +} + +/* Returns n-th damon_region of the given task */ +struct damon_region *damon_nth_region_of(struct damon_task *t, unsigned int n) +{ + struct damon_region *r; + unsigned int i = 0; + + damon_for_each_region(r, t) { + if (i++ == n) + return r; + } + + return NULL; +} + +static void damon_add_task(struct damon_ctx *ctx, struct damon_task *t) +{ + list_add_tail(&t->list, &ctx->tasks_list); +} + +static void damon_del_task(struct damon_task *t) +{ + list_del(&t->list); +} + +static void damon_free_task(struct damon_task *t) +{ + struct damon_region *r, *next; + + damon_for_each_region_safe(r, next, t) + damon_free_region(r); + kfree(t); +} + +static void damon_destroy_task(struct damon_task *t) +{ + damon_del_task(t); + damon_free_task(t); +} + +static unsigned int nr_damon_tasks(struct damon_ctx *ctx) +{ + struct damon_task *t; + unsigned int nr_tasks = 0; + + damon_for_each_task(ctx, t) + nr_tasks++; + + return nr_tasks; +} + +static unsigned int nr_damon_regions(struct damon_task *t) +{ + struct damon_region *r; + unsigned int nr_regions = 0; + + damon_for_each_region(r, t) + nr_regions++; + + return nr_regions; +} + +static int __init damon_init(void) +{ + return 0; +} + +static void __exit damon_exit(void) +{ + return; +} + +module_init(damon_init); +module_exit(damon_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("SeongJae Park "); +MODULE_DESCRIPTION("DAMON: Data Access MONitor"); From patchwork Wed Mar 18 11:27:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: SeongJae Park X-Patchwork-Id: 11445007 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5729714DD for ; Wed, 18 Mar 2020 11:31:49 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id F073D20771 for ; Wed, 18 Mar 2020 11:31:48 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=amazon.com header.i=@amazon.com header.b="DPg8DuK0" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org F073D20771 Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=amazon.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 24AC46B000D; Wed, 18 Mar 2020 07:31:48 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 1FBFF6B0010; Wed, 18 Mar 2020 07:31:48 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 0C34C6B0037; Wed, 18 Mar 2020 07:31:48 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0030.hostedemail.com [216.40.44.30]) by kanga.kvack.org (Postfix) with ESMTP id E43996B000D for ; Wed, 18 Mar 2020 07:31:47 -0400 (EDT) Received: from smtpin25.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay02.hostedemail.com (Postfix) with ESMTP id 99E30124F for ; Wed, 18 Mar 2020 11:31:47 +0000 (UTC) X-FDA: 76608268254.25.twig78_f8c5be1c2a1e X-Spam-Summary: 1,0,0,,d41d8cd98f00b204,prvs=339ded45b=sjpark@amazon.com,,RULES_HIT:30003:30012:30034:30051:30054:30056:30064:30070:30075:30090,0,RBL:207.171.184.25:@amazon.com:.lbl8.mailshell.net-66.10.201.10 62.18.0.100,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:fp,MSBL:0,DNSBL:neutral,Custom_rules:0:0:0,LFtime:25,LUA_SUMMARY:none X-HE-Tag: twig78_f8c5be1c2a1e X-Filterd-Recvd-Size: 22261 Received: from smtp-fw-9101.amazon.com (smtp-fw-9101.amazon.com [207.171.184.25]) by imf31.hostedemail.com (Postfix) with ESMTP for ; Wed, 18 Mar 2020 11:31:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1584531107; x=1616067107; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=neDsUfB04gY3RPNNLcuJefuxYAjdtlY7vG/VCbqI9zw=; b=DPg8DuK0qzkyKMPjXlOAIQ6AWVmhgOzYSNeAqhqwsaqD2tt/y02JtKLX R1/qFDdRGUlceDV/6i5pUJeNpaCsbQmiNs2V6ayBYn8yFXK16U4PQTkSF jYD4w0MDW9ZjxZMUyMZLu/m7spB/Ji86prM3THNcq6RBVdAxPXKUjI5fj U=; IronPort-SDR: Sg4oiJNNpvrDJJo97s6k1R0Hgcijy9b+HxWxtc9jT6dnZSYLsxLZT7YDn0QZiOyDiBtMY1yPrg rqxql8UZqN7Q== X-IronPort-AV: E=Sophos;i="5.70,567,1574121600"; d="scan'208";a="23517564" Received: from sea32-co-svc-lb4-vlan3.sea.corp.amazon.com (HELO email-inbound-relay-1d-f273de60.us-east-1.amazon.com) ([10.47.23.38]) by smtp-border-fw-out-9101.sea19.amazon.com with ESMTP; 18 Mar 2020 11:31:43 +0000 Received: from EX13MTAUEA002.ant.amazon.com (iad55-ws-svc-p15-lb9-vlan2.iad.amazon.com [10.40.159.162]) by email-inbound-relay-1d-f273de60.us-east-1.amazon.com (Postfix) with ESMTPS id 2442DA2E85; Wed, 18 Mar 2020 11:31:32 +0000 (UTC) Received: from EX13D31EUA001.ant.amazon.com (10.43.165.15) by EX13MTAUEA002.ant.amazon.com (10.43.61.77) with Microsoft SMTP Server (TLS) id 15.0.1236.3; Wed, 18 Mar 2020 11:31:32 +0000 Received: from u886c93fd17d25d.ant.amazon.com (10.43.161.235) by EX13D31EUA001.ant.amazon.com (10.43.165.15) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Wed, 18 Mar 2020 11:31:16 +0000 From: SeongJae Park To: CC: SeongJae Park , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH v7 04/15] mm/damon: Implement region based sampling Date: Wed, 18 Mar 2020 12:27:11 +0100 Message-ID: <20200318112722.30143-5-sjpark@amazon.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200318112722.30143-1-sjpark@amazon.com> References: <20200318112722.30143-1-sjpark@amazon.com> MIME-Version: 1.0 X-Originating-IP: [10.43.161.235] X-ClientProxiedBy: EX13D28UWC001.ant.amazon.com (10.43.162.166) To EX13D31EUA001.ant.amazon.com (10.43.165.15) X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: From: SeongJae Park This commit implements DAMON's basic access check and region based sampling mechanisms. This change would seems make no sense, mainly because it is only a part of the DAMON's logics. Following two commits will make more sense. Basic Access Check ------------------ DAMON basically reports what pages are how frequently accessed. Note that the frequency is not an absolute number of accesses, but a relative frequency among the pages of the target workloads. Users can control the resolution of the reports by setting two time intervals, ``sampling interval`` and ``aggregation interval``. In detail, DAMON checks access to each page per ``sampling interval``, aggregates the results (counts the number of the accesses to each page), and reports the aggregated results per ``aggregation interval``. For the access check of each page, DAMON uses the Accessed bits of PTEs. This is thus similar to common periodic access checks based access tracking mechanisms, which overhead is increasing as the size of the target process grows. Region Based Sampling --------------------- To avoid the unbounded increase of the overhead, DAMON groups a number of adjacent pages that assumed to have same access frequencies into a region. As long as the assumption (pages in a region have same access frequencies) is kept, only one page in the region is required to be checked. Thus, for each ``sampling interval``, DAMON randomly picks one page in each region and clears its Accessed bit. After one more ``sampling interval``, DAMON reads the Accessed bit of the page and increases the access frequency of the region if the bit has set meanwhile. Therefore, the monitoring overhead is controllable by setting the number of regions. Nonetheless, this scheme cannot preserve the quality of the output if the assumption is not kept. Following commit will introduce how we can make the guarantee with best effort. Signed-off-by: SeongJae Park --- include/linux/damon.h | 24 ++ mm/damon.c | 553 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 577 insertions(+) diff --git a/include/linux/damon.h b/include/linux/damon.h index 7117bb7e7544..f1945df6e6b4 100644 --- a/include/linux/damon.h +++ b/include/linux/damon.h @@ -11,6 +11,8 @@ #define _DAMON_H_ #include +#include +#include #include /* Represents a monitoring target region on the virtual address space */ @@ -29,10 +31,32 @@ struct damon_task { struct list_head list; }; +/* + * For each 'sample_interval', DAMON checks whether each region is accessed or + * not. It aggregates and keeps the access information (number of accesses to + * each region) for each 'aggr_interval' time. + * + * All time intervals are in micro-seconds. + */ struct damon_ctx { + unsigned long sample_interval; + unsigned long aggr_interval; + unsigned long min_nr_regions; + + struct timespec64 last_aggregation; + + struct task_struct *kdamond; + struct mutex kdamond_lock; + struct rnd_state rndseed; struct list_head tasks_list; /* 'damon_task' objects */ }; +int damon_set_pids(struct damon_ctx *ctx, unsigned long *pids, ssize_t nr_pids); +int damon_set_attrs(struct damon_ctx *ctx, unsigned long sample_int, + unsigned long aggr_int, unsigned long min_nr_reg); +int damon_start(struct damon_ctx *ctx); +int damon_stop(struct damon_ctx *ctx); + #endif diff --git a/mm/damon.c b/mm/damon.c index d7e6226ab7f1..018016793555 100644 --- a/mm/damon.c +++ b/mm/damon.c @@ -10,8 +10,14 @@ #define pr_fmt(fmt) "damon: " fmt #include +#include +#include #include #include +#include +#include +#include +#include #include #define damon_get_task_struct(t) \ @@ -171,6 +177,553 @@ static unsigned int nr_damon_regions(struct damon_task *t) return nr_regions; } +/* + * Get the mm_struct of the given task + * + * Caller should put the mm_struct after use, unless it is NULL. + * + * Returns the mm_struct of the task on success, NULL on failure + */ +static struct mm_struct *damon_get_mm(struct damon_task *t) +{ + struct task_struct *task; + struct mm_struct *mm; + + task = damon_get_task_struct(t); + if (!task) + return NULL; + + mm = get_task_mm(task); + put_task_struct(task); + return mm; +} + +/* + * Size-evenly split a region into 'nr_pieces' small regions + * + * Returns 0 on success, or negative error code otherwise. + */ +static int damon_split_region_evenly(struct damon_ctx *ctx, + struct damon_region *r, unsigned int nr_pieces) +{ + unsigned long sz_orig, sz_piece, orig_end; + struct damon_region *piece = NULL, *next; + unsigned long start; + + if (!r || !nr_pieces) + return -EINVAL; + + orig_end = r->vm_end; + sz_orig = r->vm_end - r->vm_start; + sz_piece = sz_orig / nr_pieces; + + if (!sz_piece) + return -EINVAL; + + r->vm_end = r->vm_start + sz_piece; + next = damon_next_region(r); + for (start = r->vm_end; start + sz_piece <= orig_end; + start += sz_piece) { + piece = damon_new_region(ctx, start, start + sz_piece); + damon_insert_region(piece, r, next); + r = piece; + } + /* complement last region for possible rounding error */ + if (piece) + piece->vm_end = orig_end; + + return 0; +} + +struct region { + unsigned long start; + unsigned long end; +}; + +static unsigned long sz_region(struct region *r) +{ + return r->end - r->start; +} + +static void swap_regions(struct region *r1, struct region *r2) +{ + struct region tmp; + + tmp = *r1; + *r1 = *r2; + *r2 = tmp; +} + +/* + * Find the three regions in an address space + * + * vma the head vma of the target address space + * regions an array of three 'struct region's that results will be saved + * + * This function receives an address space and finds three regions in it which + * separated by the two biggest unmapped regions in the space. Please refer to + * below comments of 'damon_init_regions_of()' function to know why this is + * necessary. + * + * Returns 0 if success, or negative error code otherwise. + */ +static int damon_three_regions_in_vmas(struct vm_area_struct *vma, + struct region regions[3]) +{ + struct region gap = {0,}, first_gap = {0,}, second_gap = {0,}; + struct vm_area_struct *last_vma = NULL; + unsigned long start = 0; + + /* Find two biggest gaps so that first_gap > second_gap > others */ + for (; vma; vma = vma->vm_next) { + if (!last_vma) { + start = vma->vm_start; + last_vma = vma; + continue; + } + gap.start = last_vma->vm_end; + gap.end = vma->vm_start; + if (sz_region(&gap) > sz_region(&second_gap)) { + swap_regions(&gap, &second_gap); + if (sz_region(&second_gap) > sz_region(&first_gap)) + swap_regions(&second_gap, &first_gap); + } + last_vma = vma; + } + + if (!sz_region(&second_gap) || !sz_region(&first_gap)) + return -EINVAL; + + /* Sort the two biggest gaps by address */ + if (first_gap.start > second_gap.start) + swap_regions(&first_gap, &second_gap); + + /* Store the result */ + regions[0].start = start; + regions[0].end = first_gap.start; + regions[1].start = first_gap.end; + regions[1].end = second_gap.start; + regions[2].start = second_gap.end; + regions[2].end = last_vma->vm_end; + + return 0; +} + +/* + * Get the three regions in the given task + * + * Returns 0 on success, negative error code otherwise. + */ +static int damon_three_regions_of(struct damon_task *t, + struct region regions[3]) +{ + struct mm_struct *mm; + int rc; + + mm = damon_get_mm(t); + if (!mm) + return -EINVAL; + + down_read(&mm->mmap_sem); + rc = damon_three_regions_in_vmas(mm->mmap, regions); + up_read(&mm->mmap_sem); + + mmput(mm); + return rc; +} + +/* + * Initialize the monitoring target regions for the given task + * + * t the given target task + * + * Because only a number of small portions of the entire address space + * is acutally mapped to the memory and accessed, monitoring the unmapped + * regions is wasteful. That said, because we can deal with small noises, + * tracking every mapping is not strictly required but could even incur a high + * overhead if the mapping frequently changes or the number of mappings is + * high. Nonetheless, this may seems very weird. DAMON's dynamic regions + * adjustment mechanism, which will be implemented with following commit will + * make this more sense. + * + * For the reason, we convert the complex mappings to three distinct regions + * that cover every mapped areas of the address space. Also the two gaps + * between the three regions are the two biggest unmapped areas in the given + * address space. In detail, this function first identifies the start and the + * end of the mappings and the two biggest unmapped areas of the address space. + * Then, it constructs the three regions as below: + * + * [mappings[0]->start, big_two_unmapped_areas[0]->start) + * [big_two_unmapped_areas[0]->end, big_two_unmapped_areas[1]->start) + * [big_two_unmapped_areas[1]->end, mappings[nr_mappings - 1]->end) + * + * As usual memory map of processes is as below, the gap between the heap and + * the uppermost mmap()-ed region, and the gap between the lowermost mmap()-ed + * region and the stack will be two biggest unmapped regions. Because these + * gaps are exceptionally huge areas in usual address space, excluding these + * two biggest unmapped regions will be sufficient to make a trade-off. + * + * + * + * + * (other mmap()-ed regions and small unmapped regions) + * + * + * + */ +static void damon_init_regions_of(struct damon_ctx *c, struct damon_task *t) +{ + struct damon_region *r; + struct region regions[3]; + int i; + + if (damon_three_regions_of(t, regions)) { + pr_err("Failed to get three regions of task %lu\n", t->pid); + return; + } + + /* Set the initial three regions of the task */ + for (i = 0; i < 3; i++) { + r = damon_new_region(c, regions[i].start, regions[i].end); + damon_add_region(r, t); + } + + /* Split the middle region into 'min_nr_regions - 2' regions */ + r = damon_nth_region_of(t, 1); + if (damon_split_region_evenly(c, r, c->min_nr_regions - 2)) + pr_warn("Init middle region failed to be split\n"); +} + +/* Initialize '->regions_list' of every task */ +static void kdamond_init_regions(struct damon_ctx *ctx) +{ + struct damon_task *t; + + damon_for_each_task(ctx, t) + damon_init_regions_of(ctx, t); +} + +static bool damon_pte_pmd_young(pte_t *pte, pmd_t *pmd) +{ + if (pte && pte_young(*pte)) + return true; +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + if (pmd && pmd_young(*pmd)) + return true; +#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ + return false; +} + +static void damon_pte_pmd_mkold(pte_t *pte, pmd_t *pmd) +{ + if (pte) { + if (pte_young(*pte)) { + clear_page_idle(pte_page(*pte)); + set_page_young(pte_page(*pte)); + } + *pte = pte_mkold(*pte); + return; + } +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + if (pmd) { + if (pmd_young(*pmd)) { + clear_page_idle(pmd_page(*pmd)); + set_page_young(pmd_page(*pmd)); + } + *pmd = pmd_mkold(*pmd); + } +#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ +} + +/* + * Check whether the region accessed and prepare for next check + * + * mm 'mm_struct' for the given virtual address space + * r the region to be checked + */ +static void kdamond_check_access(struct damon_ctx *ctx, + struct mm_struct *mm, struct damon_region *r) +{ + static struct mm_struct *last_mm; + static unsigned long last_addr; + static int last_page_sz = PAGE_SIZE; + static bool last_accessed; + + pte_t *pte = NULL; + pmd_t *pmd = NULL; + spinlock_t *ptl; + + /* If the region is in the last checked page, reuse the result */ + if (mm == last_mm && (ALIGN_DOWN(last_addr, last_page_sz) == + ALIGN_DOWN(r->sampling_addr, last_page_sz))) { + if (last_accessed) + r->nr_accesses++; + return; + } + + if (follow_pte_pmd(mm, r->sampling_addr, NULL, &pte, &pmd, &ptl)) + goto prepare_next_check; + + /* Read the page table access bit of the page */ + if (damon_pte_pmd_young(pte, pmd)) { + last_accessed = true; + r->nr_accesses++; + } + spin_unlock(ptl); + +prepare_next_check: + last_mm = mm; + last_addr = r->sampling_addr; +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + last_page_sz = pte ? PAGE_SIZE : ((1UL) << HPAGE_PMD_SHIFT); +#endif + + r->sampling_addr = damon_rand(ctx, r->vm_start, r->vm_end); + pte = NULL, pmd = NULL; + if (follow_pte_pmd(mm, r->sampling_addr, NULL, &pte, &pmd, &ptl)) + return; + + damon_pte_pmd_mkold(pte, pmd); + spin_unlock(ptl); +} + +/* + * damon_check_reset_time_interval() - Check if a time interval is elapsed. + * @baseline: the time to check whether the interval has elapsed since + * @interval: the time interval (microseconds) + * + * See whether the given time interval has passed since the given baseline + * time. If so, it also updates the baseline to current time for next check. + * + * Return: true if the time interval has passed, or false otherwise. + */ +static bool damon_check_reset_time_interval(struct timespec64 *baseline, + unsigned long interval) +{ + struct timespec64 now; + + ktime_get_coarse_ts64(&now); + if ((timespec64_to_ns(&now) - timespec64_to_ns(baseline)) < + interval * 1000) + return false; + *baseline = now; + return true; +} + +/* + * Check whether it is time to flush the aggregated information + */ +static bool kdamond_aggregate_interval_passed(struct damon_ctx *ctx) +{ + return damon_check_reset_time_interval(&ctx->last_aggregation, + ctx->aggr_interval); +} + +/* + * Reset the aggregated monitoring results + */ +static void kdamond_reset_aggregated(struct damon_ctx *c) +{ + struct damon_task *t; + struct damon_region *r; + + damon_for_each_task(c, t) { + damon_for_each_region(r, t) + r->nr_accesses = 0; + } +} + +/* + * Check whether current monitoring should be stopped + * + * If users asked to stop, need stop. Even though no user has asked to stop, + * need stop if every target task has dead. + * + * Returns true if need to stop current monitoring. + */ +static bool kdamond_need_stop(struct damon_ctx *ctx) +{ + struct damon_task *t; + struct task_struct *task; + bool stop; + + stop = kthread_should_stop(); + if (stop) + return true; + + damon_for_each_task(ctx, t) { + task = damon_get_task_struct(t); + if (task) { + put_task_struct(task); + return false; + } + } + + return true; +} + +/* + * The monitoring daemon that runs as a kernel thread + */ +static int kdamond_fn(void *data) +{ + struct damon_ctx *ctx = data; + struct damon_task *t; + struct damon_region *r, *next; + struct mm_struct *mm; + + pr_info("kdamond (%d) starts\n", ctx->kdamond->pid); + kdamond_init_regions(ctx); + while (!kdamond_need_stop(ctx)) { + damon_for_each_task(ctx, t) { + mm = damon_get_mm(t); + if (!mm) + continue; + damon_for_each_region(r, t) + kdamond_check_access(ctx, mm, r); + mmput(mm); + } + + if (kdamond_aggregate_interval_passed(ctx)) + kdamond_reset_aggregated(ctx); + + usleep_range(ctx->sample_interval, ctx->sample_interval + 1); + } + damon_for_each_task(ctx, t) { + damon_for_each_region_safe(r, next, t) + damon_destroy_region(r); + } + pr_debug("kdamond (%d) finishes\n", ctx->kdamond->pid); + mutex_lock(&ctx->kdamond_lock); + ctx->kdamond = NULL; + mutex_unlock(&ctx->kdamond_lock); + + return 0; +} + +/* + * Controller functions + */ + +static bool damon_kdamond_running(struct damon_ctx *ctx) +{ + bool running; + + mutex_lock(&ctx->kdamond_lock); + running = ctx->kdamond != NULL; + mutex_unlock(&ctx->kdamond_lock); + + return running; +} + +/* + * Start or stop the kdamond + * + * Returns 0 if success, negative error code otherwise. + */ +static int damon_turn_kdamond(struct damon_ctx *ctx, bool on) +{ + int err = -EBUSY; + + mutex_lock(&ctx->kdamond_lock); + if (!ctx->kdamond && on) { + err = 0; + ctx->kdamond = kthread_run(kdamond_fn, ctx, "kdamond"); + if (IS_ERR(ctx->kdamond)) + err = PTR_ERR(ctx->kdamond); + } else if (ctx->kdamond && !on) { + mutex_unlock(&ctx->kdamond_lock); + kthread_stop(ctx->kdamond); + while (damon_kdamond_running(ctx)) + usleep_range(ctx->sample_interval, + ctx->sample_interval * 2); + return 0; + } + mutex_unlock(&ctx->kdamond_lock); + + return err; +} + +/* + * damon_start() - Starts monitoring with given context. + * @ctx: monitoring context + * + * Return: 0 on success, negative error code otherwise. + */ +int damon_start(struct damon_ctx *ctx) +{ + return damon_turn_kdamond(ctx, true); +} + +/* + * damon_stop() - Stops monitoring of given context. + * @ctx: monitoring context + * + * Return: 0 on success, negative error code otherwise. + */ +int damon_stop(struct damon_ctx *ctx) +{ + return damon_turn_kdamond(ctx, false); +} + +/* + * damon_set_pids() - Set monitoring target processes. + * @ctx: monitoring context + * @pids: array of target processes pids + * @nr_pids: number of entries in @pids + * + * This function should not be called while the kdamond is running. + * + * Return: 0 on usccess, negative error code otherwise. + */ +int damon_set_pids(struct damon_ctx *ctx, unsigned long *pids, ssize_t nr_pids) +{ + ssize_t i; + struct damon_task *t, *next; + + damon_for_each_task_safe(ctx, t, next) + damon_destroy_task(t); + + for (i = 0; i < nr_pids; i++) { + t = damon_new_task(pids[i]); + if (!t) { + pr_err("Failed to alloc damon_task\n"); + return -ENOMEM; + } + damon_add_task(ctx, t); + } + + return 0; +} + +/* + * damon_set_attrs() - Set attributes for the monitoring. + * @ctx: monitoring context + * @sample_int: time interval between samplings + * @aggr_int: time interval between aggregations + * @min_nr_reg: minimal number of regions + * + * This function should not be called while the kdamond is running. + * Every time interval is in micro-seconds. + * + * Return: 0 on success, negative error code otherwise. + */ +int damon_set_attrs(struct damon_ctx *ctx, unsigned long sample_int, + unsigned long aggr_int, unsigned long min_nr_reg) +{ + if (min_nr_reg < 3) { + pr_err("min_nr_regions (%lu) should be bigger than 2\n", + min_nr_reg); + return -EINVAL; + } + + ctx->sample_interval = sample_int; + ctx->aggr_interval = aggr_int; + ctx->min_nr_regions = min_nr_reg; + + return 0; +} + static int __init damon_init(void) { return 0; From patchwork Wed Mar 18 11:27:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: SeongJae Park X-Patchwork-Id: 11445009 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 180591392 for ; Wed, 18 Mar 2020 11:32:17 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id BE59A2076D for ; Wed, 18 Mar 2020 11:32:16 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=amazon.com header.i=@amazon.com header.b="WmrTxXnY" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org BE59A2076D Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=amazon.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id F1CA86B0010; Wed, 18 Mar 2020 07:32:15 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id EF4156B0037; Wed, 18 Mar 2020 07:32:15 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id DE2A06B006C; Wed, 18 Mar 2020 07:32:15 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0054.hostedemail.com [216.40.44.54]) by kanga.kvack.org (Postfix) with ESMTP id C5DA46B0010 for ; Wed, 18 Mar 2020 07:32:15 -0400 (EDT) Received: from smtpin08.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay04.hostedemail.com (Postfix) with ESMTP id 826ED3D0F for ; Wed, 18 Mar 2020 11:32:15 +0000 (UTC) X-FDA: 76608269430.08.hour20_13a9405376840 X-Spam-Summary: 1,0,0,,d41d8cd98f00b204,prvs=339ded45b=sjpark@amazon.com,,RULES_HIT:30003:30012:30034:30045:30054:30056:30064:30070:30090,0,RBL:72.21.196.25:@amazon.com:.lbl8.mailshell.net-62.18.0.100 66.10.201.10,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:fp,MSBL:0,DNSBL:neutral,Custom_rules:0:0:0,LFtime:37,LUA_SUMMARY:none X-HE-Tag: hour20_13a9405376840 X-Filterd-Recvd-Size: 12289 Received: from smtp-fw-2101.amazon.com (smtp-fw-2101.amazon.com [72.21.196.25]) by imf13.hostedemail.com (Postfix) with ESMTP for ; Wed, 18 Mar 2020 11:32:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1584531136; x=1616067136; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=hUg47B/NPqGh/qIzop0zsaEUWXywSo9IMWG6tHKTkpk=; b=WmrTxXnYgkmPSPWBlodDFM8K9IBVnm8LywlLRHkbFoxMbjrLGvjXaC2P LRc+fi5/ZhumjHr4EUbirt+D57YtGY++IzmeOwEuADD5uO6iVI8XXKIJV lMLcAWB7kSrVJKnT9Co6ZQo6SxOl+4QQuDpumt4vJjBaT9ghnJas4POzQ k=; IronPort-SDR: 6wNHDJ0xFH1sghY3ERIldN3kUjgUrfMyBrXx6v3m4UuKsGMXuumyjwYBzrq/Fj07GOZBXBcnsS elXTYTpIHSrg== X-IronPort-AV: E=Sophos;i="5.70,567,1574121600"; d="scan'208";a="22002456" Received: from iad12-co-svc-p1-lb1-vlan2.amazon.com (HELO email-inbound-relay-1a-e34f1ddc.us-east-1.amazon.com) ([10.43.8.2]) by smtp-border-fw-out-2101.iad2.amazon.com with ESMTP; 18 Mar 2020 11:32:03 +0000 Received: from EX13MTAUEA002.ant.amazon.com (iad55-ws-svc-p15-lb9-vlan2.iad.amazon.com [10.40.159.162]) by email-inbound-relay-1a-e34f1ddc.us-east-1.amazon.com (Postfix) with ESMTPS id 27C34A2D85; Wed, 18 Mar 2020 11:31:52 +0000 (UTC) Received: from EX13D31EUA001.ant.amazon.com (10.43.165.15) by EX13MTAUEA002.ant.amazon.com (10.43.61.77) with Microsoft SMTP Server (TLS) id 15.0.1236.3; Wed, 18 Mar 2020 11:31:52 +0000 Received: from u886c93fd17d25d.ant.amazon.com (10.43.161.235) by EX13D31EUA001.ant.amazon.com (10.43.165.15) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Wed, 18 Mar 2020 11:31:36 +0000 From: SeongJae Park To: CC: SeongJae Park , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH v7 05/15] mm/damon: Adaptively adjust regions Date: Wed, 18 Mar 2020 12:27:12 +0100 Message-ID: <20200318112722.30143-6-sjpark@amazon.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200318112722.30143-1-sjpark@amazon.com> References: <20200318112722.30143-1-sjpark@amazon.com> MIME-Version: 1.0 X-Originating-IP: [10.43.161.235] X-ClientProxiedBy: EX13D28UWC001.ant.amazon.com (10.43.162.166) To EX13D31EUA001.ant.amazon.com (10.43.165.15) X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: From: SeongJae Park At the beginning of the monitoring, DAMON constructs the initial regions by evenly splitting the memory mapped address space of the process into the user-specified minimal number of regions. In this initial state, the assumption of the regions (pages in same region have similar access frequencies) is normally not kept and thus the monitoring quality could be low. To keep the assumption as much as possible, DAMON adaptively merges and splits each region. For each ``aggregation interval``, it compares the access frequencies of adjacent regions and merges those if the frequency difference is small. Then, after it reports and clears the aggregated access frequency of each region, it splits each region into two regions if the total number of regions is smaller than the half of the user-specified maximum number of regions. In this way, DAMON provides its best-effort quality and minimal overhead while keeping the bounds users set for their trade-off. Signed-off-by: SeongJae Park --- include/linux/damon.h | 6 +- mm/damon.c | 148 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 145 insertions(+), 9 deletions(-) diff --git a/include/linux/damon.h b/include/linux/damon.h index f1945df6e6b4..7562b85b1ec0 100644 --- a/include/linux/damon.h +++ b/include/linux/damon.h @@ -42,6 +42,7 @@ struct damon_ctx { unsigned long sample_interval; unsigned long aggr_interval; unsigned long min_nr_regions; + unsigned long max_nr_regions; struct timespec64 last_aggregation; @@ -54,8 +55,9 @@ struct damon_ctx { }; int damon_set_pids(struct damon_ctx *ctx, unsigned long *pids, ssize_t nr_pids); -int damon_set_attrs(struct damon_ctx *ctx, unsigned long sample_int, - unsigned long aggr_int, unsigned long min_nr_reg); +int damon_set_attrs(struct damon_ctx *ctx, + unsigned long sample_int, unsigned long aggr_int, + unsigned long min_nr_reg, unsigned long max_nr_reg); int damon_start(struct damon_ctx *ctx); int damon_stop(struct damon_ctx *ctx); diff --git a/mm/damon.c b/mm/damon.c index 018016793555..23c0de3b502e 100644 --- a/mm/damon.c +++ b/mm/damon.c @@ -342,9 +342,12 @@ static int damon_three_regions_of(struct damon_task *t, * regions is wasteful. That said, because we can deal with small noises, * tracking every mapping is not strictly required but could even incur a high * overhead if the mapping frequently changes or the number of mappings is - * high. Nonetheless, this may seems very weird. DAMON's dynamic regions - * adjustment mechanism, which will be implemented with following commit will - * make this more sense. + * high. The adaptive regions adjustment mechanism will further help to deal + * with the noises by simply identifying the unmapped areas as a region that + * has no access. Moreover, applying the real mappings that would have many + * unmapped areas inside will make the adaptive mechanism quite complex. That + * said, too huge unmapped areas inside the monitoring target should be removed + * to not take the time for the adaptive mechanism. * * For the reason, we convert the complex mappings to three distinct regions * that cover every mapped areas of the address space. Also the two gaps @@ -533,6 +536,121 @@ static void kdamond_reset_aggregated(struct damon_ctx *c) } } +#define sz_damon_region(r) (r->vm_end - r->vm_start) + +/* + * Merge two adjacent regions into one region + */ +static void damon_merge_two_regions(struct damon_region *l, + struct damon_region *r) +{ + l->nr_accesses = (l->nr_accesses * sz_damon_region(l) + + r->nr_accesses * sz_damon_region(r)) / + (sz_damon_region(l) + sz_damon_region(r)); + l->vm_end = r->vm_end; + damon_destroy_region(r); +} + +#define diff_of(a, b) (a > b ? a - b : b - a) + +/* + * Merge adjacent regions having similar access frequencies + * + * t task that merge operation will make change + * thres merge regions having '->nr_accesses' diff smaller than this + */ +static void damon_merge_regions_of(struct damon_task *t, unsigned int thres) +{ + struct damon_region *r, *prev = NULL, *next; + + damon_for_each_region_safe(r, next, t) { + if (!prev || prev->vm_end != r->vm_start || + diff_of(prev->nr_accesses, r->nr_accesses) > thres) { + prev = r; + continue; + } + damon_merge_two_regions(prev, r); + } +} + +/* + * Merge adjacent regions having similar access frequencies + * + * threshold merge regions havind nr_accesses diff larger than this + * + * This function merges monitoring target regions which are adjacent and their + * access frequencies are similar. This is for minimizing the monitoring + * overhead under the dynamically changeable access pattern. If a merge was + * unnecessarily made, later 'kdamond_split_regions()' will revert it. + */ +static void kdamond_merge_regions(struct damon_ctx *c, unsigned int threshold) +{ + struct damon_task *t; + + damon_for_each_task(c, t) + damon_merge_regions_of(t, threshold); +} + +/* + * Split a region into two small regions + * + * r the region to be split + * sz_r size of the first sub-region that will be made + */ +static void damon_split_region_at(struct damon_ctx *ctx, + struct damon_region *r, unsigned long sz_r) +{ + struct damon_region *new; + + new = damon_new_region(ctx, r->vm_start + sz_r, r->vm_end); + r->vm_end = new->vm_start; + + damon_insert_region(new, r, damon_next_region(r)); +} + +static void damon_split_regions_of(struct damon_ctx *ctx, struct damon_task *t) +{ + struct damon_region *r, *next; + unsigned long sz_left_region; + + damon_for_each_region_safe(r, next, t) { + /* + * Randomly select size of left sub-region to be at least + * 10 percent and at most 90% of original region + */ + sz_left_region = (prandom_u32_state(&ctx->rndseed) % 9 + 1) * + (r->vm_end - r->vm_start) / 10; + /* Do not allow blank region */ + if (sz_left_region == 0) + continue; + damon_split_region_at(ctx, r, sz_left_region); + } +} + +/* + * splits every target regions into two randomly-sized regions + * + * This function splits every target regions into two random-sized regions if + * current total number of the regions is smaller than the half of the + * user-specified maximum number of regions. This is for maximizing the + * monitoring accuracy under the dynamically changeable access patterns. If a + * split was unnecessarily made, later 'kdamond_merge_regions()' will revert + * it. + */ +static void kdamond_split_regions(struct damon_ctx *ctx) +{ + struct damon_task *t; + unsigned int nr_regions = 0; + + damon_for_each_task(ctx, t) + nr_regions += nr_damon_regions(t); + if (nr_regions > ctx->max_nr_regions / 2) + return; + + damon_for_each_task(ctx, t) + damon_split_regions_of(ctx, t); +} + /* * Check whether current monitoring should be stopped * @@ -571,21 +689,29 @@ static int kdamond_fn(void *data) struct damon_task *t; struct damon_region *r, *next; struct mm_struct *mm; + unsigned int max_nr_accesses; pr_info("kdamond (%d) starts\n", ctx->kdamond->pid); kdamond_init_regions(ctx); while (!kdamond_need_stop(ctx)) { + max_nr_accesses = 0; damon_for_each_task(ctx, t) { mm = damon_get_mm(t); if (!mm) continue; - damon_for_each_region(r, t) + damon_for_each_region(r, t) { kdamond_check_access(ctx, mm, r); + max_nr_accesses = max(r->nr_accesses, + max_nr_accesses); + } mmput(mm); } - if (kdamond_aggregate_interval_passed(ctx)) + if (kdamond_aggregate_interval_passed(ctx)) { + kdamond_merge_regions(ctx, max_nr_accesses / 10); kdamond_reset_aggregated(ctx); + kdamond_split_regions(ctx); + } usleep_range(ctx->sample_interval, ctx->sample_interval + 1); } @@ -702,24 +828,32 @@ int damon_set_pids(struct damon_ctx *ctx, unsigned long *pids, ssize_t nr_pids) * @sample_int: time interval between samplings * @aggr_int: time interval between aggregations * @min_nr_reg: minimal number of regions + * @max_nr_reg: maximum number of regions * * This function should not be called while the kdamond is running. * Every time interval is in micro-seconds. * * Return: 0 on success, negative error code otherwise. */ -int damon_set_attrs(struct damon_ctx *ctx, unsigned long sample_int, - unsigned long aggr_int, unsigned long min_nr_reg) +int damon_set_attrs(struct damon_ctx *ctx, + unsigned long sample_int, unsigned long aggr_int, + unsigned long min_nr_reg, unsigned long max_nr_reg) { if (min_nr_reg < 3) { pr_err("min_nr_regions (%lu) should be bigger than 2\n", min_nr_reg); return -EINVAL; } + if (min_nr_reg >= ctx->max_nr_regions) { + pr_err("invalid nr_regions. min (%lu) >= max (%lu)\n", + min_nr_reg, max_nr_reg); + return -EINVAL; + } ctx->sample_interval = sample_int; ctx->aggr_interval = aggr_int; ctx->min_nr_regions = min_nr_reg; + ctx->max_nr_regions = max_nr_reg; return 0; } From patchwork Wed Mar 18 11:27:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: SeongJae Park X-Patchwork-Id: 11445011 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9B5371392 for ; Wed, 18 Mar 2020 11:32:34 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 5B3052076D for ; Wed, 18 Mar 2020 11:32:34 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=amazon.com header.i=@amazon.com header.b="PMVNaiSx" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5B3052076D Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=amazon.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 975946B0037; Wed, 18 Mar 2020 07:32:33 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 927D96B006C; Wed, 18 Mar 2020 07:32:33 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 83D736B0073; Wed, 18 Mar 2020 07:32:33 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0030.hostedemail.com [216.40.44.30]) by kanga.kvack.org (Postfix) with ESMTP id 6B4806B0037 for ; Wed, 18 Mar 2020 07:32:33 -0400 (EDT) Received: from smtpin17.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay03.hostedemail.com (Postfix) with ESMTP id 2D728824556B for ; Wed, 18 Mar 2020 11:32:33 +0000 (UTC) X-FDA: 76608270186.17.sofa10_163c45b0a9a19 X-Spam-Summary: 1,0,0,,d41d8cd98f00b204,prvs=339ded45b=sjpark@amazon.com,,RULES_HIT:30003:30012:30034:30054:30056:30064:30070:30075,0,RBL:72.21.196.25:@amazon.com:.lbl8.mailshell.net-62.18.0.100 66.10.201.10,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:fp,MSBL:0,DNSBL:neutral,Custom_rules:0:0:0,LFtime:23,LUA_SUMMARY:none X-HE-Tag: sofa10_163c45b0a9a19 X-Filterd-Recvd-Size: 9405 Received: from smtp-fw-2101.amazon.com (smtp-fw-2101.amazon.com [72.21.196.25]) by imf32.hostedemail.com (Postfix) with ESMTP for ; Wed, 18 Mar 2020 11:32:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1584531153; x=1616067153; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=9JLpSR/hpH6Y1WsOsdGzWbBnkGtgStWv6JmQH3em5Xc=; b=PMVNaiSxcrtbXOrRCqUK5kkdIKM8gNIlTOkMVS6fxKjEHnUzi2xwtbsE OzTE2w6IZ1LFKVnor3aQM+m9lZwJ4I+eKFju5I3uKKXMAWBKJ2k3X+OKZ 2X5ArK6pS5PiOSZtooo2lk3InfTQHT+5HY/kGrD1ynaLLL0YBhQF/bAl6 g=; IronPort-SDR: v4ArqjtWhnIt+YxBgPW2aJGAvBO5f+0hGzDqNbGEBDbAfFLPG0h2RLQpzjySIWgf6IBh1cisp5 J3b6c+smyZ+A== X-IronPort-AV: E=Sophos;i="5.70,567,1574121600"; d="scan'208";a="22002491" Received: from iad12-co-svc-p1-lb1-vlan2.amazon.com (HELO email-inbound-relay-1a-807d4a99.us-east-1.amazon.com) ([10.43.8.2]) by smtp-border-fw-out-2101.iad2.amazon.com with ESMTP; 18 Mar 2020 11:32:33 +0000 Received: from EX13MTAUEA002.ant.amazon.com (iad55-ws-svc-p15-lb9-vlan2.iad.amazon.com [10.40.159.162]) by email-inbound-relay-1a-807d4a99.us-east-1.amazon.com (Postfix) with ESMTPS id 82C74A18E6; Wed, 18 Mar 2020 11:32:22 +0000 (UTC) Received: from EX13D31EUA001.ant.amazon.com (10.43.165.15) by EX13MTAUEA002.ant.amazon.com (10.43.61.77) with Microsoft SMTP Server (TLS) id 15.0.1236.3; Wed, 18 Mar 2020 11:32:21 +0000 Received: from u886c93fd17d25d.ant.amazon.com (10.43.161.235) by EX13D31EUA001.ant.amazon.com (10.43.165.15) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Wed, 18 Mar 2020 11:32:04 +0000 From: SeongJae Park To: CC: SeongJae Park , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH v7 06/15] mm/damon: Apply dynamic memory mapping changes Date: Wed, 18 Mar 2020 12:27:13 +0100 Message-ID: <20200318112722.30143-7-sjpark@amazon.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200318112722.30143-1-sjpark@amazon.com> References: <20200318112722.30143-1-sjpark@amazon.com> MIME-Version: 1.0 X-Originating-IP: [10.43.161.235] X-ClientProxiedBy: EX13D28UWC001.ant.amazon.com (10.43.162.166) To EX13D31EUA001.ant.amazon.com (10.43.165.15) X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: From: SeongJae Park Only a number of parts in the virtual address space of the processes is mapped to physical memory and accessed. Thus, tracking the unmapped address regions is just wasteful. However, tracking every memory mapping change might incur an overhead. For the reason, DAMON applies the dynamic memory mapping changes to the tracking regions only for each of a user-specified time interval (``regions update interval``). Signed-off-by: SeongJae Park --- include/linux/damon.h | 10 +++-- mm/damon.c | 92 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 96 insertions(+), 6 deletions(-) diff --git a/include/linux/damon.h b/include/linux/damon.h index 7562b85b1ec0..64e327400749 100644 --- a/include/linux/damon.h +++ b/include/linux/damon.h @@ -34,17 +34,21 @@ struct damon_task { /* * For each 'sample_interval', DAMON checks whether each region is accessed or * not. It aggregates and keeps the access information (number of accesses to - * each region) for each 'aggr_interval' time. + * each region) for 'aggr_interval' time. DAMON also checks whether the memory + * mapping of the target tasks has changed (e.g., by mmap() calls from the + * application) and applies the changes. for each 'regions_update_interval'. * * All time intervals are in micro-seconds. */ struct damon_ctx { unsigned long sample_interval; unsigned long aggr_interval; + unsigned long regions_update_interval; unsigned long min_nr_regions; unsigned long max_nr_regions; struct timespec64 last_aggregation; + struct timespec64 last_regions_update; struct task_struct *kdamond; struct mutex kdamond_lock; @@ -55,8 +59,8 @@ struct damon_ctx { }; int damon_set_pids(struct damon_ctx *ctx, unsigned long *pids, ssize_t nr_pids); -int damon_set_attrs(struct damon_ctx *ctx, - unsigned long sample_int, unsigned long aggr_int, +int damon_set_attrs(struct damon_ctx *ctx, unsigned long sample_int, + unsigned long aggr_int, unsigned long regions_update_int, unsigned long min_nr_reg, unsigned long max_nr_reg); int damon_start(struct damon_ctx *ctx); int damon_stop(struct damon_ctx *ctx); diff --git a/mm/damon.c b/mm/damon.c index 23c0de3b502e..535337529d20 100644 --- a/mm/damon.c +++ b/mm/damon.c @@ -651,6 +651,87 @@ static void kdamond_split_regions(struct damon_ctx *ctx) damon_split_regions_of(ctx, t); } +/* + * Check whether it is time to check and apply the dynamic mmap changes + * + * Returns true if it is. + */ +static bool kdamond_need_update_regions(struct damon_ctx *ctx) +{ + return damon_check_reset_time_interval(&ctx->last_regions_update, + ctx->regions_update_interval); +} + +static bool damon_intersect(struct damon_region *r, struct region *re) +{ + return !(r->vm_end <= re->start || re->end <= r->vm_start); +} + +/* + * Update damon regions for the three big regions of the given task + * + * t the given task + * bregions the three big regions of the task + */ +static void damon_apply_three_regions(struct damon_ctx *ctx, + struct damon_task *t, struct region bregions[3]) +{ + struct damon_region *r, *next; + unsigned int i = 0; + + /* Remove regions which isn't in the three big regions now */ + damon_for_each_region_safe(r, next, t) { + for (i = 0; i < 3; i++) { + if (damon_intersect(r, &bregions[i])) + break; + } + if (i == 3) + damon_destroy_region(r); + } + + /* Adjust intersecting regions to fit with the three big regions */ + for (i = 0; i < 3; i++) { + struct damon_region *first = NULL, *last; + struct damon_region *newr; + struct region *br; + + br = &bregions[i]; + /* Get the first and last regions which intersects with br */ + damon_for_each_region(r, t) { + if (damon_intersect(r, br)) { + if (!first) + first = r; + last = r; + } + if (r->vm_start >= br->end) + break; + } + if (!first) { + /* no damon_region intersects with this big region */ + newr = damon_new_region(ctx, br->start, br->end); + damon_insert_region(newr, damon_prev_region(r), r); + } else { + first->vm_start = br->start; + last->vm_end = br->end; + } + } +} + +/* + * Update regions for current memory mappings + */ +static void kdamond_update_regions(struct damon_ctx *ctx) +{ + struct region three_regions[3]; + struct damon_task *t; + + damon_for_each_task(ctx, t) { + if (damon_three_regions_of(t, three_regions)) + continue; + damon_apply_three_regions(ctx, t, three_regions); + } +} + /* * Check whether current monitoring should be stopped * @@ -713,6 +794,9 @@ static int kdamond_fn(void *data) kdamond_split_regions(ctx); } + if (kdamond_need_update_regions(ctx)) + kdamond_update_regions(ctx); + usleep_range(ctx->sample_interval, ctx->sample_interval + 1); } damon_for_each_task(ctx, t) { @@ -826,6 +910,7 @@ int damon_set_pids(struct damon_ctx *ctx, unsigned long *pids, ssize_t nr_pids) * damon_set_attrs() - Set attributes for the monitoring. * @ctx: monitoring context * @sample_int: time interval between samplings + * @regions_update_int: time interval between vma update checks * @aggr_int: time interval between aggregations * @min_nr_reg: minimal number of regions * @max_nr_reg: maximum number of regions @@ -835,9 +920,9 @@ int damon_set_pids(struct damon_ctx *ctx, unsigned long *pids, ssize_t nr_pids) * * Return: 0 on success, negative error code otherwise. */ -int damon_set_attrs(struct damon_ctx *ctx, - unsigned long sample_int, unsigned long aggr_int, - unsigned long min_nr_reg, unsigned long max_nr_reg) +int damon_set_attrs(struct damon_ctx *ctx, unsigned long sample_int, + unsigned long aggr_int, unsigned long regions_update_int, + unsigned long min_nr_reg, unsigned long max_nr_reg) { if (min_nr_reg < 3) { pr_err("min_nr_regions (%lu) should be bigger than 2\n", @@ -852,6 +937,7 @@ int damon_set_attrs(struct damon_ctx *ctx, ctx->sample_interval = sample_int; ctx->aggr_interval = aggr_int; + ctx->regions_update_interval = regions_update_int; ctx->min_nr_regions = min_nr_reg; ctx->max_nr_regions = max_nr_reg; From patchwork Wed Mar 18 11:27:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: SeongJae Park X-Patchwork-Id: 11445013 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4F19214DD for ; Wed, 18 Mar 2020 11:32:56 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 1A28520771 for ; Wed, 18 Mar 2020 11:32:56 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=amazon.com header.i=@amazon.com header.b="r2Pzfefe" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1A28520771 Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=amazon.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 57EED6B000D; Wed, 18 Mar 2020 07:32:55 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 52E6D6B006C; Wed, 18 Mar 2020 07:32:55 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 41F2C6B0073; Wed, 18 Mar 2020 07:32:55 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0248.hostedemail.com [216.40.44.248]) by kanga.kvack.org (Postfix) with ESMTP id 2C5856B000D for ; Wed, 18 Mar 2020 07:32:55 -0400 (EDT) Received: from smtpin21.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay03.hostedemail.com (Postfix) with ESMTP id CD5268245571 for ; Wed, 18 Mar 2020 11:32:54 +0000 (UTC) X-FDA: 76608271068.21.smoke32_19614d8e5b353 X-Spam-Summary: 1,0,0,,d41d8cd98f00b204,prvs=339ded45b=sjpark@amazon.com,,RULES_HIT:30054:30064,0,RBL:207.171.190.10:@amazon.com:.lbl8.mailshell.net-66.10.201.10 62.18.0.100,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:fp,MSBL:0,DNSBL:neutral,Custom_rules:0:0:0,LFtime:23,LUA_SUMMARY:none X-HE-Tag: smoke32_19614d8e5b353 X-Filterd-Recvd-Size: 4749 Received: from smtp-fw-33001.amazon.com (smtp-fw-33001.amazon.com [207.171.190.10]) by imf04.hostedemail.com (Postfix) with ESMTP for ; Wed, 18 Mar 2020 11:32:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1584531175; x=1616067175; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=IIweUbJ6ywSxmEcEsqVWoNZ/WqTFK20tUG13PKDxXU8=; b=r2Pzfefe1BUMtbCotQrPl/iIIqzUqOresoK7kcW3RlXjRLQ71HfaylVa rjG3DJb7FoNg06KBtDJf4nL4JgEanzeHvlARjqChf0L1P+o2BZIw85P6y VqKaZ6e1q4MK03LOGPpJIfpDO6nthk/HRWIuYaf7WvIhSfhmB4dj4JmMX Y=; IronPort-SDR: ETsYFwWCXdqiKtV6jfvVJ1un7t8wySL4whgPWQh+9JbcrMmEtsPTXOPvBfEhrozL4akLUT1+Cz xz06oDSJsiKw== X-IronPort-AV: E=Sophos;i="5.70,567,1574121600"; d="scan'208";a="33271215" Received: from sea32-co-svc-lb4-vlan3.sea.corp.amazon.com (HELO email-inbound-relay-1e-27fb8269.us-east-1.amazon.com) ([10.47.23.38]) by smtp-border-fw-out-33001.sea14.amazon.com with ESMTP; 18 Mar 2020 11:32:51 +0000 Received: from EX13MTAUEA002.ant.amazon.com (iad55-ws-svc-p15-lb9-vlan3.iad.amazon.com [10.40.159.166]) by email-inbound-relay-1e-27fb8269.us-east-1.amazon.com (Postfix) with ESMTPS id 428FFA0333; Wed, 18 Mar 2020 11:32:40 +0000 (UTC) Received: from EX13D31EUA001.ant.amazon.com (10.43.165.15) by EX13MTAUEA002.ant.amazon.com (10.43.61.77) with Microsoft SMTP Server (TLS) id 15.0.1236.3; Wed, 18 Mar 2020 11:32:40 +0000 Received: from u886c93fd17d25d.ant.amazon.com (10.43.161.235) by EX13D31EUA001.ant.amazon.com (10.43.165.15) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Wed, 18 Mar 2020 11:32:26 +0000 From: SeongJae Park To: CC: SeongJae Park , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH v7 07/15] mm/damon: Implement callbacks Date: Wed, 18 Mar 2020 12:27:14 +0100 Message-ID: <20200318112722.30143-8-sjpark@amazon.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200318112722.30143-1-sjpark@amazon.com> References: <20200318112722.30143-1-sjpark@amazon.com> MIME-Version: 1.0 X-Originating-IP: [10.43.161.235] X-ClientProxiedBy: EX13D28UWC001.ant.amazon.com (10.43.162.166) To EX13D31EUA001.ant.amazon.com (10.43.165.15) X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: From: SeongJae Park This commit implements callbacks for DAMON. Using this, DAMON users can install their callbacks for each step of the access monitoring so that they can do something interesting with the monitored access patterns online. For example, callbacks can report the monitored patterns to users or do some access pattern based memory management such as proactive reclamations or access pattern based THP promotions/demotions decision makings. Signed-off-by: SeongJae Park --- include/linux/damon.h | 4 ++++ mm/damon.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/include/linux/damon.h b/include/linux/damon.h index 64e327400749..cad3ee3d78db 100644 --- a/include/linux/damon.h +++ b/include/linux/damon.h @@ -56,6 +56,10 @@ struct damon_ctx { struct rnd_state rndseed; struct list_head tasks_list; /* 'damon_task' objects */ + + /* callbacks */ + void (*sample_cb)(struct damon_ctx *context); + void (*aggregate_cb)(struct damon_ctx *context); }; int damon_set_pids(struct damon_ctx *ctx, unsigned long *pids, ssize_t nr_pids); diff --git a/mm/damon.c b/mm/damon.c index 535337529d20..2e8af1ce4389 100644 --- a/mm/damon.c +++ b/mm/damon.c @@ -787,9 +787,13 @@ static int kdamond_fn(void *data) } mmput(mm); } + if (ctx->sample_cb) + ctx->sample_cb(ctx); if (kdamond_aggregate_interval_passed(ctx)) { kdamond_merge_regions(ctx, max_nr_accesses / 10); + if (ctx->aggregate_cb) + ctx->aggregate_cb(ctx); kdamond_reset_aggregated(ctx); kdamond_split_regions(ctx); } From patchwork Wed Mar 18 11:27:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: SeongJae Park X-Patchwork-Id: 11445015 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D7B5414DD for ; Wed, 18 Mar 2020 11:33:45 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 9AFA42076D for ; Wed, 18 Mar 2020 11:33:45 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=amazon.com header.i=@amazon.com header.b="p3saGtPp" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 9AFA42076D Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=amazon.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id CAACC6B0010; Wed, 18 Mar 2020 07:33:44 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id C5A5A6B0037; Wed, 18 Mar 2020 07:33:44 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id B70436B006C; Wed, 18 Mar 2020 07:33:44 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0128.hostedemail.com [216.40.44.128]) by kanga.kvack.org (Postfix) with ESMTP id 9BF146B0010 for ; Wed, 18 Mar 2020 07:33:44 -0400 (EDT) Received: from smtpin30.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay05.hostedemail.com (Postfix) with ESMTP id 47D57181AEF0B for ; Wed, 18 Mar 2020 11:33:44 +0000 (UTC) X-FDA: 76608273168.30.test90_2095d05781a16 X-Spam-Summary: 1,0,0,,d41d8cd98f00b204,prvs=339ded45b=sjpark@amazon.com,,RULES_HIT:30003:30012:30034:30051:30054:30064:30070:30075,0,RBL:72.21.196.25:@amazon.com:.lbl8.mailshell.net-62.18.0.100 66.10.201.10,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:fp,MSBL:0,DNSBL:neutral,Custom_rules:0:0:0,LFtime:24,LUA_SUMMARY:none X-HE-Tag: test90_2095d05781a16 X-Filterd-Recvd-Size: 9232 Received: from smtp-fw-2101.amazon.com (smtp-fw-2101.amazon.com [72.21.196.25]) by imf50.hostedemail.com (Postfix) with ESMTP for ; Wed, 18 Mar 2020 11:33:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1584531225; x=1616067225; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=s0AfyZ6CiQ6AzJS05n/GM916ac2WmoGpXpoaffAKTPY=; b=p3saGtPpSuoKmxTvO2FY2vQN4+/PEK2FPefK6Isvl6by1wbVpSuNkGSL M+BRY0DiwW4yJ8WToUOdseEwRCL1aedhYjbtDp26Pve7WyVMMv+pTxTH9 UcHpK877UyKeT5cZnHvudOnKE6OKWzbpivORQVfvW0f2DinqZDqPb+bFG s=; IronPort-SDR: ODNl+8upXqZPtYW0Y6p5MvnEOupndjxY/OoQ+9dHBo6dRPKg+lr3MHLx3F8aevk1QFZqwDrqGv WT5HT4ca0wAQ== X-IronPort-AV: E=Sophos;i="5.70,567,1574121600"; d="scan'208";a="22002595" Received: from iad12-co-svc-p1-lb1-vlan2.amazon.com (HELO email-inbound-relay-1a-7d76a15f.us-east-1.amazon.com) ([10.43.8.2]) by smtp-border-fw-out-2101.iad2.amazon.com with ESMTP; 18 Mar 2020 11:33:44 +0000 Received: from EX13MTAUEA002.ant.amazon.com (iad55-ws-svc-p15-lb9-vlan2.iad.amazon.com [10.40.159.162]) by email-inbound-relay-1a-7d76a15f.us-east-1.amazon.com (Postfix) with ESMTPS id BA158A26C4; Wed, 18 Mar 2020 11:33:33 +0000 (UTC) Received: from EX13D31EUA001.ant.amazon.com (10.43.165.15) by EX13MTAUEA002.ant.amazon.com (10.43.61.77) with Microsoft SMTP Server (TLS) id 15.0.1236.3; Wed, 18 Mar 2020 11:33:32 +0000 Received: from u886c93fd17d25d.ant.amazon.com (10.43.161.235) by EX13D31EUA001.ant.amazon.com (10.43.165.15) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Wed, 18 Mar 2020 11:33:14 +0000 From: SeongJae Park To: CC: SeongJae Park , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH v7 08/15] mm/damon: Implement access pattern recording Date: Wed, 18 Mar 2020 12:27:15 +0100 Message-ID: <20200318112722.30143-9-sjpark@amazon.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200318112722.30143-1-sjpark@amazon.com> References: <20200318112722.30143-1-sjpark@amazon.com> MIME-Version: 1.0 X-Originating-IP: [10.43.161.235] X-ClientProxiedBy: EX13D28UWC001.ant.amazon.com (10.43.162.166) To EX13D31EUA001.ant.amazon.com (10.43.165.15) X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: From: SeongJae Park This commit implements the recording feature of DAMON. If this feature is enabled, DAMON writes the monitored access patterns in its binary format into a file which specified by the user. This is already able to be implemented by each user using the callbacks. However, as the recording is expected to be used widely, this commit implements the feature in the DAMON, for more convenience and efficiency. Signed-off-by: SeongJae Park --- include/linux/damon.h | 7 +++ mm/damon.c | 120 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 124 insertions(+), 3 deletions(-) diff --git a/include/linux/damon.h b/include/linux/damon.h index cad3ee3d78db..47fb0ec03030 100644 --- a/include/linux/damon.h +++ b/include/linux/damon.h @@ -50,6 +50,11 @@ struct damon_ctx { struct timespec64 last_aggregation; struct timespec64 last_regions_update; + unsigned char *rbuf; + unsigned int rbuf_len; + unsigned int rbuf_offset; + char *rfile_path; + struct task_struct *kdamond; struct mutex kdamond_lock; @@ -66,6 +71,8 @@ int damon_set_pids(struct damon_ctx *ctx, unsigned long *pids, ssize_t nr_pids); int damon_set_attrs(struct damon_ctx *ctx, unsigned long sample_int, unsigned long aggr_int, unsigned long regions_update_int, unsigned long min_nr_reg, unsigned long max_nr_reg); +int damon_set_recording(struct damon_ctx *ctx, + unsigned int rbuf_len, char *rfile_path); int damon_start(struct damon_ctx *ctx); int damon_stop(struct damon_ctx *ctx); diff --git a/mm/damon.c b/mm/damon.c index 2e8af1ce4389..59d49b0990cf 100644 --- a/mm/damon.c +++ b/mm/damon.c @@ -41,6 +41,8 @@ #define damon_for_each_task_safe(ctx, t, next) \ list_for_each_entry_safe(t, next, &(ctx)->tasks_list, list) +#define MAX_RFILE_PATH_LEN 256 + /* Get a random number in [l, r) */ #define damon_rand(ctx, l, r) (l + prandom_u32_state(&ctx->rndseed) % (r - l)) @@ -523,16 +525,81 @@ static bool kdamond_aggregate_interval_passed(struct damon_ctx *ctx) } /* - * Reset the aggregated monitoring results + * Flush the content in the result buffer to the result file + */ +static void damon_flush_rbuffer(struct damon_ctx *ctx) +{ + ssize_t sz; + loff_t pos; + struct file *rfile; + + while (ctx->rbuf_offset) { + pos = 0; + rfile = filp_open(ctx->rfile_path, O_CREAT | O_RDWR | O_APPEND, + 0644); + if (IS_ERR(rfile)) { + pr_err("Cannot open the result file %s\n", + ctx->rfile_path); + return; + } + + sz = kernel_write(rfile, ctx->rbuf, ctx->rbuf_offset, &pos); + filp_close(rfile, NULL); + + ctx->rbuf_offset -= sz; + } +} + +/* + * Write a data into the result buffer + */ +static void damon_write_rbuf(struct damon_ctx *ctx, void *data, ssize_t size) +{ + if (!ctx->rbuf_len || !ctx->rbuf) + return; + if (ctx->rbuf_offset + size > ctx->rbuf_len) + damon_flush_rbuffer(ctx); + + memcpy(&ctx->rbuf[ctx->rbuf_offset], data, size); + ctx->rbuf_offset += size; +} + +/* + * Flush the aggregated monitoring results to the result buffer + * + * Stores current tracking results to the result buffer and reset 'nr_accesses' + * of each regions. The format for the result buffer is as below: + * + *