Received: by 2002:a05:6a10:17d3:0:0:0:0 with SMTP id hz19csp2917301pxb; Tue, 13 Apr 2021 13:36:36 -0700 (PDT) X-Google-Smtp-Source: ABdhPJx8BwXh73306JwTrD4gMn40D8RXSO7ByGDZqjoPJJ2pmlR0df2SPi7J901QaNY4wjc2juBV X-Received: by 2002:a17:906:e84:: with SMTP id p4mr33908128ejf.248.1618346196268; Tue, 13 Apr 2021 13:36:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1618346196; cv=none; d=google.com; s=arc-20160816; b=nuIUzhlRERGpCbauvSFAP4ZDplhPmf7kHxDvpycqxgT3Qu62uxruHh8ShVo1IoH6qa XzknxAmqSWKfLcWwBP7E2zAlhwY55TZAxWsL+FqpfrtmjVhOGiVHT2QaEnaYA8dSVkmv 4JblE8wAkKbiim8YwAI4VAfGb2yPDCJRo4o3B0Ig6mYYOw1ws5vYB8L0IBWSl6FUMtQ/ X6u5lHYW2X7dH2N2woiRZ4JAN7o/n97eeIJAQpCW8XSGmlzOTOVKdwAqpvVl5PJiDYEW Qwg2ubmRLOV4L9DMt0O2SS256dcmOp7/S97ViIkqRB5x+rJ3SmnJ0pOp4HXlTYLqlaUp 1TnA== 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=oBcikesh7GyPN9E8SBJMMuqucOH5hp7CfWnrE8VKzJQ=; b=wRZuwOHWCWqPYfVcdSEF9Ub8GKPdmgkSrYsmK/IVOG32v8y3o6cy7TO0FtGU/X3Agu O7EvV7IX7M6pKIDM5uSu7ziwKs/2KUkZlRUiMcEqFFthMUTjjbGsCYZ9OdRWOLWNDlmv VwW6uF4rJolFWPCSE8dnvxQZy9vpfSGtFdg53Ze+TEKnMAxsbsYdcHtgmuZJUcxRhSnk EXLIY9X4PQKYjBRVHsFPmCHQ1EzjGz4qXLd23JmOAbE3Yc01OPA4suIkdMOzhhNIvsYQ wo3ZNnHSZp0Hoe8W9sIdKB6ZouSfoUBfHyR2qZMhkGKU/PWcHdn/BBr5wP95s5O2KNpn 3kKQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=D9tLB6RY; 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 d25si10019611eje.106.2021.04.13.13.36.13; Tue, 13 Apr 2021 13:36:36 -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=D9tLB6RY; 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 S1346428AbhDMObJ (ORCPT + 99 others); Tue, 13 Apr 2021 10:31:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59468 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239290AbhDMO34 (ORCPT ); Tue, 13 Apr 2021 10:29:56 -0400 Received: from mail-qk1-x72b.google.com (mail-qk1-x72b.google.com [IPv6:2607:f8b0:4864:20::72b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 96AD2C06138E; Tue, 13 Apr 2021 07:29:36 -0700 (PDT) Received: by mail-qk1-x72b.google.com with SMTP id b139so12595287qkc.10; Tue, 13 Apr 2021 07:29:36 -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=oBcikesh7GyPN9E8SBJMMuqucOH5hp7CfWnrE8VKzJQ=; b=D9tLB6RYox8ns/lsPJYUqwxUpGU5fnGkCMxegPL45GhzdDJAbRzf+bK1ruWyEqD1tU FKSphZCE4bnvQL3o1+txFQopryplzChGMf/hd1WhPWk7PkJY8YmmGBIzwwZZCiU1qspP u7vbjq4HAV1PGE2SCvMWTiwJ+x65PwJTWkmgfDIzU6/kygAVJyOOLq0shM7+guisNGRu y69yIePEUFBVgU0PfLV8FYKtqn5VMLM9EzUQT7nsvMMFqNUEb29HpsLQQ6GNlKQVUiW1 2PA4xIRo/OTFJiF+2pUKol7HK1gQxm8Mu6vco3WUpmgUmS1q4+MrH2Xapoy5o/DrH91a RgxQ== 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=oBcikesh7GyPN9E8SBJMMuqucOH5hp7CfWnrE8VKzJQ=; b=M8tWg5S0u4lR9MNVbsCZK37mqw4Qe1Ho14PiLObnycAXoC8TL88zbcJLaWY9j8Ve3w J+i6UiUO1bsaK0VTR38ndEgp9jcIBQo6eVoy23EKqrrMLD9ZNkPkEUuAJns4Hf4++kD9 e4YSCIRN9gED9OYAB5amnulP2ekSAXVIe2lxRHR0c71YAl+U8oMrozLUlF6rpj8guwCS uQsXyekDPEAcclOWq6NSQ+4oB2f7lIfRLeDBsjavReO2wxQqsDWCcbbnuikQsraNRIgx qsvFB5tPYHvFKkQaUxdA5tD9fjpXPAez58w15D0kV1628gqUCfeTFerQlXBP3V1DYh7z 5TjQ== X-Gm-Message-State: AOAM533SfpnEq2YkIDGT+ZaMKRWbkaPDRj5xWrFFQQAijvoctOcnR+wE 4b/1XvBQy8muw7lHEG93Bmg= X-Received: by 2002:a37:b007:: with SMTP id z7mr24294473qke.215.1618324175800; Tue, 13 Apr 2021 07:29:35 -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 2sm6160911qko.134.2021.04.13.07.29.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 13 Apr 2021 07:29:35 -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 v28 09/13] mm/damon/dbgfs: Support multiple contexts Date: Tue, 13 Apr 2021 14:29:00 +0000 Message-Id: <20210413142904.556-10-sj38.park@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210413142904.556-1-sj38.park@gmail.com> References: <20210413142904.556-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 | 197 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 195 insertions(+), 2 deletions(-) diff --git a/mm/damon/dbgfs.c b/mm/damon/dbgfs.c index 67b273472c0b..734bc14f0100 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. @@ -314,6 +315,186 @@ 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; + + 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; + dbgfs_ctxs = new_ctxs; + + new_dirs = krealloc(dbgfs_dirs, sizeof(*dbgfs_dirs) * + (dbgfs_nr_ctxs + 1), GFP_KERNEL); + if (!new_dirs) + return -ENOMEM; + 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; + dbgfs_fill_ctx_dir(dbgfs_dirs[dbgfs_nr_ctxs], + dbgfs_ctxs[dbgfs_nr_ctxs]); + 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) { @@ -356,6 +537,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, @@ -365,8 +556,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