Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp4215976pxf; Tue, 30 Mar 2021 02:10:00 -0700 (PDT) X-Google-Smtp-Source: ABdhPJy2HZ2JBLIA1gLuU0WfRspvNIOVW1dKGat3j+6JbKyb8NQAu8wtKKFjzFspmmHzj52O0n3H X-Received: by 2002:a17:907:689:: with SMTP id wn9mr32146878ejb.485.1617095400127; Tue, 30 Mar 2021 02:10:00 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1617095400; cv=none; d=google.com; s=arc-20160816; b=NO3USrOa6WRuJ4W+fngHyr9v1gif1c2r2k6Kf5Jfo+2I0av0YXGN5XUCEQAa6/VxDw 7n1Sio0MJ5V2E2kwxjumu41ppty7RzxoslXiue6h1MmGcu1EmZIX9RgjFmJiqqvpl4yn C+mKZH7+q55l6OOQaS/T8bueD3UFGU7Yz/g6ollSD+1WYA+nRLrtP/cqII1a6/gqEfRV ZCziB17FW6wyvS46jb444BxvxpauBcfbb9Fv+WOcHE8xvY7MzPEjXRxC0eZFraAP7mBW cCBrPNQx4qYMJ0gDCgX/HuykDTaOoe4U9GFOI7eO5XnFd4aTVwi+7aYKKnRhTo+mx9IX ZL8g== 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=aKeb3fcwK9W0TVkoKsvlqPl7wq54ptWNz0E2zQWWcJc=; b=WunueTr3rOxMiqGSIQa6ddSeBfrpio4o1wU3vvqZdNZtojivdBfwI97D9/LXo0anaJ LIqs5Wdms+kAJoXCbWyhzRRKvDc5uQz8JUzUoew6XyRNDTgkx0g1OwZ8BlSF8/Yhx5Ab yYQpYTWcoVbNZiztaU+ZhvSqrfK2ttvSAE38ZlklOkO1h+A4W9IQ2cp9VKllRHt6i+an jvj6dMeYIHnrNb6E/vZqr9XI5JFG+lUCboZNNN1DGfmCOl/moxq4LUaPYxI1VORu/PLE 4AQ0g6YPMuYHDxDsThy0aY5dm7nwQrHS0bwWHz3Qe6NiQYDc/qsglHRlS4KKRXxCfSQY eluA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=BYecdWPw; 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 eb8si7774340edb.353.2021.03.30.02.09.37; Tue, 30 Mar 2021 02:10:00 -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=BYecdWPw; 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 S231743AbhC3JGv (ORCPT + 99 others); Tue, 30 Mar 2021 05:06:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59980 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231722AbhC3JGQ (ORCPT ); Tue, 30 Mar 2021 05:06:16 -0400 Received: from mail-qv1-xf33.google.com (mail-qv1-xf33.google.com [IPv6:2607:f8b0:4864:20::f33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1E459C061762; Tue, 30 Mar 2021 02:06:16 -0700 (PDT) Received: by mail-qv1-xf33.google.com with SMTP id x27so7793818qvd.2; Tue, 30 Mar 2021 02:06:16 -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=aKeb3fcwK9W0TVkoKsvlqPl7wq54ptWNz0E2zQWWcJc=; b=BYecdWPwi+adIwOrQ1jwjvyQ7upZg1baANTvcj2drxbRgYceMVktNiTwSqd/tx/yo+ WX71o2A9v5DIe6ivJGbFJJARhq+hgGM9OsqncEY+vvPtxTafdE9Vh0n1wQttibs8M6fK ZlF7NJssAfm4ItTq9ja2YkCadxGtSp0bnwiZ/KqfCK+vkuKRxf52YGhktRHRPZUd+Sd5 Cak3Efu4YTS0PGGyS6vpze7+XPxv0jescjQEdBdN9XxOeCa6Gy1S5h2luqAwfbBk/qDk Fna28JG/qJuNtrp4/eJv7tCBeTwVLZhGvjkjpi5pHiYt0OfRduwflUfDUf/0m2f1NmiA sVww== 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=aKeb3fcwK9W0TVkoKsvlqPl7wq54ptWNz0E2zQWWcJc=; b=nK1ZIciVFEvqwsVpktPyie20val5Y5RYaFHoqYucQncpXsTpkE6ujE70HIttkMwI0Z CjvD3qGoJu7TAABcc3cssvS5KahD1e/Es62VPtIAlJbTrKR2yfb0UMZocwdBAGM5nohM 0Vcz3Sf1DyPYQR1RsIotzm3nOPE3TnJ+T7sfGCeBeKmUvCxXqEr+XOtzHEOM5uR5Ocpf yvSMOXHJqvtyWGv0+yEm4MLzlgpqj2S32DWLXzjX3PjsCu4pkwSm0fULMHAw3CNjngZy Op9O60GSpTQOIEfDwXAQbYZwZwcU94Sbs5PyBTxWaL/JvSxHgliSz+8YxyGPD1y16AEK VqkA== X-Gm-Message-State: AOAM530jEGEfrzx3QmXlMHNHFH6xHweIc980Tu8BLvO5n2ySRg2O7lwB bdKSHMv5IPEDBV30qLaSLZc= X-Received: by 2002:a0c:f349:: with SMTP id e9mr29271201qvm.59.1617095175306; Tue, 30 Mar 2021 02:06:15 -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 8sm14630011qkc.32.2021.03.30.02.06.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Mar 2021 02:06:14 -0700 (PDT) From: sj38.park@gmail.com 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 v26 09/13] mm/damon/dbgfs: Support multiple contexts Date: Tue, 30 Mar 2021 09:05:33 +0000 Message-Id: <20210330090537.12143-10-sj38.park@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210330090537.12143-1-sj38.park@gmail.com> References: <20210330090537.12143-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 aec2b7d81809..9edef931ed00 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