Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp467347pxf; Thu, 8 Apr 2021 06:51:25 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxgfHGOag/8QAlSRUB2Q7KcKDOsab7gNUfer/yaGoOahG4lPOQDYEsGth3IGqDhFGP0cnMk X-Received: by 2002:a17:906:7c4:: with SMTP id m4mr10641210ejc.63.1617889885518; Thu, 08 Apr 2021 06:51:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1617889885; cv=none; d=google.com; s=arc-20160816; b=Q12OplQag6PjFg2+yjAqFAvlWQpvMS4j7qrhZFQRP3H6t4HQ0DHAFLmp8O3nDenAM2 XP/8YrxAcdfQIgTaeAy0kCKPF3xsjWXbpJ7feoNtBCOy1KaJTtX6tq7Ngu3VByDszI0f aR0G6iwfyDzM2ywsKUlPl0Eoi1hiTI98Uc2g6jgPfcxYpNDVV5p/W2Dejdd+S6NsfUTt aPO4/8sftpYzJmNAXL5HfwVx4gOpjh3V7L6fDg4tP/Oy9lLvDYfIBvoz+gYF/pe5Mocu zTDNeL8IKJvJ83WOi/wLyFxz4aE5G6qE48OaHXSLbsRUvwv/7oAlKIn5nA3puDYXKbIS tr5w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:references:in-reply-to:message-id:date:subject :cc:to:from:dkim-signature; bh=5OBkv83RGov9L/3QCpgvK/oOzcbyJ6M4mfwMXxAb7rY=; b=rbsx/4wbBTDLXMzCSZV067BljFLzH2bA5p9iIQkpTMYtwwHDeot78bdmn48pK7+v1m WTjQDUbXUzQl8gyp9RDDYgLmSxryIx1j8/h0uogowPjo9YnEsVRRN+L32urdufS1UZ6b +QIKU5mm74D+WAudcwl3HC24hx8/+aFmAeW/6cdu1WW+ooYnmoVQxJwXeET/uSkmdEe1 ZAItk9c2cmnaVecc+cEvI3YJ143OiPWEefqh7RnmtzVYNvrKJLrtWRD6foTGfhLa1DtU hlGnu/KkBxCGzzJwEW5wLZZhC3V3il6aqFwJgHv19UshGxdRE1OHBVryqbcHbn7jS5eX WsUg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=a5792wa4; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id lu3si8899492ejb.560.2021.04.08.06.50.59; Thu, 08 Apr 2021 06:51:25 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=a5792wa4; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231894AbhDHNuA (ORCPT + 99 others); Thu, 8 Apr 2021 09:50:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43308 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231791AbhDHNti (ORCPT ); Thu, 8 Apr 2021 09:49:38 -0400 Received: from mail-qt1-x829.google.com (mail-qt1-x829.google.com [IPv6:2607:f8b0:4864:20::829]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C8B85C061760; Thu, 8 Apr 2021 06:49:26 -0700 (PDT) Received: by mail-qt1-x829.google.com with SMTP id f12so1411940qtq.4; Thu, 08 Apr 2021 06:49:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=5OBkv83RGov9L/3QCpgvK/oOzcbyJ6M4mfwMXxAb7rY=; b=a5792wa4hystfPCJDAfrq2RN5xkeKgwCwxW5oI4FblBadP+ju88hICKCi29T3ll1FP DRmYoYs5OJYaVLGjyP0h+sMyG5DqW63X70ucquAkcoSgHf3hDpsVjCo9bKKzAb5esL31 S3afoKR8nuLPA8159UNRYnbEVe1smuSC1HpznUW3n5SCZSPFJhf1f4QFGZn8eoNw4goh XYtwBCkg+FRDTuHudVVYR92lgFOiQu5zkLWPYJoy4UieRGJGW8widNhe0BfdDdPl1lKe H0sQuyfP/Vx+nSREmfPMgf/UJPfrYuPPF68vMWtTZYVw1mIf4FOU8Yl9PHkREGtk/VSB 57mA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=5OBkv83RGov9L/3QCpgvK/oOzcbyJ6M4mfwMXxAb7rY=; b=cG/jM5p26TZhqphAc9ShPmHtYTR+VX7hg49eaNE0dukKyRR6eU/tNsxaPrduPgAL3F IBbvf5XztSXzSj/Ih5k4x/NAAWlbQrML9v6SMnAGWkjsVthyrbEHzeBeKITBnhePGcWa AX3HfnVZ7HIhyx4NJpkBT+DPVE7jO6dNG4vlt+nTRfEPUKAndg+wPImhAu/kx6VdzGFG WduIOsdEUMOisrmBrI9W5YQGyUnFxJSXbfWWKFB1dkw4kdwLsnSZWXp9IEsVH8ILnz0Q F+IRiNnQSS2Lk+ByFPMMIYBpVrXjRhJa4skMInL9qEkoJSs/veknSeqmso3nxZeGRfZg sH3A== X-Gm-Message-State: AOAM5313awNTKSK4SRHB2WqFKIzvPogGuT14OK5ki38NJnVG9ttBXrjZ Zcqo+/a+XrEC2N1/eVNVNMc= X-Received: by 2002:ac8:730d:: with SMTP id x13mr7587259qto.95.1617889766068; Thu, 08 Apr 2021 06:49:26 -0700 (PDT) Received: from localhost.localdomain (ec2-35-169-212-159.compute-1.amazonaws.com. [35.169.212.159]) by smtp.gmail.com with ESMTPSA id h16sm506094qkh.18.2021.04.08.06.49.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 08 Apr 2021 06:49:25 -0700 (PDT) From: SeongJae Park To: akpm@linux-foundation.org Cc: SeongJae Park , Jonathan.Cameron@Huawei.com, acme@kernel.org, alexander.shishkin@linux.intel.com, amit@kernel.org, benh@kernel.crashing.org, brendanhiggins@google.com, corbet@lwn.net, david@redhat.com, dwmw@amazon.com, elver@google.com, fan.du@intel.com, foersleo@amazon.de, greg@kroah.com, gthelen@google.com, guoju.fgj@alibaba-inc.com, mgorman@suse.de, minchan@kernel.org, mingo@redhat.com, namhyung@kernel.org, peterz@infradead.org, riel@surriel.com, rientjes@google.com, rostedt@goodmis.org, rppt@kernel.org, shakeelb@google.com, shuah@kernel.org, sj38.park@gmail.com, snu@amazon.de, vbabka@suse.cz, vdavydov.dev@gmail.com, zgf574564920@gmail.com, linux-damon@amazon.com, linux-mm@kvack.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v27 09/13] mm/damon/dbgfs: Support multiple contexts Date: Thu, 8 Apr 2021 13:48:50 +0000 Message-Id: <20210408134854.31625-10-sj38.park@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210408134854.31625-1-sj38.park@gmail.com> References: <20210408134854.31625-1-sj38.park@gmail.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: SeongJae Park In some use cases, users would want to run multiple monitoring context. For example, if a user wants a high precision monitoring and dedicating multiple CPUs for the job is ok, because DAMON creates one monitoring thread per one context, the user can split the monitoring target regions into multiple small regions and create one context for each region. Or, someone might want to simultaneously monitor different address spaces, e.g., both virtual address space and physical address space. The DAMON's API allows such usage, but 'damon-dbgfs' does not. Therefore, only kernel space DAMON users can do multiple contexts monitoring. This commit allows the user space DAMON users to use multiple contexts monitoring by introducing two new 'damon-dbgfs' debugfs files, 'mk_context' and 'rm_context'. Users can create a new monitoring context by writing the desired name of the new context to 'mk_context'. Then, a new directory with the name and having the files for setting of the context ('attrs', 'target_ids' and 'record') will be created under the debugfs directory. Writing the name of the context to remove to 'rm_context' will remove the related context and directory. Signed-off-by: SeongJae Park --- mm/damon/dbgfs.c | 203 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 201 insertions(+), 2 deletions(-) diff --git a/mm/damon/dbgfs.c b/mm/damon/dbgfs.c index b20c1e7742ce..66ac7e18b1df 100644 --- a/mm/damon/dbgfs.c +++ b/mm/damon/dbgfs.c @@ -18,6 +18,7 @@ static struct damon_ctx **dbgfs_ctxs; static int dbgfs_nr_ctxs; static struct dentry **dbgfs_dirs; +static DEFINE_MUTEX(damon_dbgfs_lock); /* * Returns non-empty string on success, negarive error code otherwise. @@ -316,6 +317,192 @@ static struct damon_ctx *dbgfs_new_ctx(void) return ctx; } +static void dbgfs_destroy_ctx(struct damon_ctx *ctx) +{ + damon_destroy_ctx(ctx); +} + +/* + * Make a context of @name and create a debugfs directory for it. + * + * This function should be called while holding damon_dbgfs_lock. + * + * Returns 0 on success, negative error code otherwise. + */ +static int dbgfs_mk_context(char *name) +{ + struct dentry *root, **new_dirs, *new_dir; + struct damon_ctx **new_ctxs, *new_ctx; + int err; + + if (damon_nr_running_ctxs()) + return -EBUSY; + + new_ctxs = krealloc(dbgfs_ctxs, sizeof(*dbgfs_ctxs) * + (dbgfs_nr_ctxs + 1), GFP_KERNEL); + if (!new_ctxs) + return -ENOMEM; + + new_dirs = krealloc(dbgfs_dirs, sizeof(*dbgfs_dirs) * + (dbgfs_nr_ctxs + 1), GFP_KERNEL); + if (!new_dirs) { + kfree(new_ctxs); + return -ENOMEM; + } + + dbgfs_ctxs = new_ctxs; + dbgfs_dirs = new_dirs; + + root = dbgfs_dirs[0]; + if (!root) + return -ENOENT; + + new_dir = debugfs_create_dir(name, root); + dbgfs_dirs[dbgfs_nr_ctxs] = new_dir; + + new_ctx = dbgfs_new_ctx(); + if (!new_ctx) { + debugfs_remove(new_dir); + dbgfs_dirs[dbgfs_nr_ctxs] = NULL; + return -ENOMEM; + } + dbgfs_ctxs[dbgfs_nr_ctxs] = new_ctx; + + err = dbgfs_fill_ctx_dir(dbgfs_dirs[dbgfs_nr_ctxs], + dbgfs_ctxs[dbgfs_nr_ctxs]); + if (err) + return err; + + dbgfs_nr_ctxs++; + return 0; +} + +static ssize_t dbgfs_mk_context_write(struct file *file, + const char __user *buf, size_t count, loff_t *ppos) +{ + char *kbuf; + char *ctx_name; + ssize_t ret = count; + int err; + + kbuf = user_input_str(buf, count, ppos); + if (IS_ERR(kbuf)) + return PTR_ERR(kbuf); + ctx_name = kmalloc(count + 1, GFP_KERNEL); + if (!ctx_name) { + kfree(kbuf); + return -ENOMEM; + } + + /* Trim white space */ + if (sscanf(kbuf, "%s", ctx_name) != 1) { + ret = -EINVAL; + goto out; + } + + mutex_lock(&damon_dbgfs_lock); + err = dbgfs_mk_context(ctx_name); + if (err) + ret = err; + mutex_unlock(&damon_dbgfs_lock); + +out: + kfree(kbuf); + kfree(ctx_name); + return ret; +} + +/* + * Remove a context of @name and its debugfs directory. + * + * This function should be called while holding damon_dbgfs_lock. + * + * Return 0 on success, negative error code otherwise. + */ +static int dbgfs_rm_context(char *name) +{ + struct dentry *root, *dir, **new_dirs; + struct damon_ctx **new_ctxs; + int i, j; + + if (damon_nr_running_ctxs()) + return -EBUSY; + + root = dbgfs_dirs[0]; + if (!root) + return -ENOENT; + + dir = debugfs_lookup(name, root); + if (!dir) + return -ENOENT; + + new_dirs = kmalloc_array(dbgfs_nr_ctxs - 1, sizeof(*dbgfs_dirs), + GFP_KERNEL); + if (!new_dirs) + return -ENOMEM; + + new_ctxs = kmalloc_array(dbgfs_nr_ctxs - 1, sizeof(*dbgfs_ctxs), + GFP_KERNEL); + if (!new_ctxs) { + kfree(new_dirs); + return -ENOMEM; + } + + for (i = 0, j = 0; i < dbgfs_nr_ctxs; i++) { + if (dbgfs_dirs[i] == dir) { + debugfs_remove(dbgfs_dirs[i]); + dbgfs_destroy_ctx(dbgfs_ctxs[i]); + continue; + } + new_dirs[j] = dbgfs_dirs[i]; + new_ctxs[j++] = dbgfs_ctxs[i]; + } + + kfree(dbgfs_dirs); + kfree(dbgfs_ctxs); + + dbgfs_dirs = new_dirs; + dbgfs_ctxs = new_ctxs; + dbgfs_nr_ctxs--; + + return 0; +} + +static ssize_t dbgfs_rm_context_write(struct file *file, + const char __user *buf, size_t count, loff_t *ppos) +{ + char *kbuf; + ssize_t ret = count; + int err; + char *ctx_name; + + kbuf = user_input_str(buf, count, ppos); + if (IS_ERR(kbuf)) + return PTR_ERR(kbuf); + ctx_name = kmalloc(count + 1, GFP_KERNEL); + if (!ctx_name) { + kfree(kbuf); + return -ENOMEM; + } + + /* Trim white space */ + if (sscanf(kbuf, "%s", ctx_name) != 1) { + ret = -EINVAL; + goto out; + } + + mutex_lock(&damon_dbgfs_lock); + err = dbgfs_rm_context(ctx_name); + if (err) + ret = err; + mutex_unlock(&damon_dbgfs_lock); + +out: + kfree(kbuf); + kfree(ctx_name); + return ret; +} + static ssize_t dbgfs_monitor_on_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { @@ -358,6 +545,16 @@ static ssize_t dbgfs_monitor_on_write(struct file *file, return ret; } +static const struct file_operations mk_contexts_fops = { + .owner = THIS_MODULE, + .write = dbgfs_mk_context_write, +}; + +static const struct file_operations rm_contexts_fops = { + .owner = THIS_MODULE, + .write = dbgfs_rm_context_write, +}; + static const struct file_operations monitor_on_fops = { .owner = THIS_MODULE, .read = dbgfs_monitor_on_read, @@ -367,8 +564,10 @@ static const struct file_operations monitor_on_fops = { static int __init __damon_dbgfs_init(void) { struct dentry *dbgfs_root; - const char * const file_names[] = {"monitor_on"}; - const struct file_operations *fops[] = {&monitor_on_fops}; + const char * const file_names[] = {"mk_contexts", "rm_contexts", + "monitor_on"}; + const struct file_operations *fops[] = {&mk_contexts_fops, + &rm_contexts_fops, &monitor_on_fops}; int i; dbgfs_root = debugfs_create_dir("damon", NULL); -- 2.17.1