Received: by 2002:a05:6a10:206:0:0:0:0 with SMTP id 6csp2149426pxj; Thu, 20 May 2021 00:59:18 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzX877pnUAocbkyU8anU9qpg9LdOmUrbfOMVNZ02B0JsYiVGZNLMpF16irsQX+937sfpj/A X-Received: by 2002:aa7:cc97:: with SMTP id p23mr3619636edt.372.1621497558491; Thu, 20 May 2021 00:59:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1621497558; cv=none; d=google.com; s=arc-20160816; b=Cv4ypfr/AH78G2yx6Fce/otv8119flaJ+E53xZElxYXbgx5nHuvcIUEBvNbpfyqhad 8in6oTU9JpngGUbTcwf2ckG61ihSmcZOYibuondZX8xnEqPENf10Kxio0pQllP/GrZZl wCgmD9GAGQqJH3qstczpJZKc9arYNmizEXL8GnW4rskmSnI2cAkCBvuOBaq7CtR3J+gS QMPKCrpWVo2S2QaRfcYFR1PaM3VE9jf07BbhRShIlNJfpSnXyKTWW8VIsTpuqUC4NFOS BdNgy1IQqTu+ArqF9i0RKzOy3uDb7mZM7G8I3cEg3gHncGwySdhofNTjAehK8EZGjLQ5 5xSg== 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=wbm5G6zeWR34g821wxpYPqLhz7MXRzZElTUgh4Gz4WVN8oItpVrKhlUqWJ1xPSHFe6 wXSitF+NJn+vpxrAkpRxo4xM9zRYizdewahh4WuT2ERZ1ERBRqTDHdnHvZDhOOXvVMpO xqEvCgM/Yqul1WtPH6/vOXGadoxZyb8G3ExFZOwZT1rzHUSbZHkZv1C4KkzLNuEMVQEb UF6jovFZG66yyO4LAgFVLmctM9BeibVSHYqWeqyogfnnvDrDNhZWbURFWuEOdpK2fw3/ AW29Pd8CL+ge/1DaDOfnVOUNJNE/HOe6nL6WZi5errL+ptkGxmr9OIBUNllNTBHENW97 6UKg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=ulLpOVHL; 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 p2si1596354edh.431.2021.05.20.00.58.55; Thu, 20 May 2021 00:59:18 -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=ulLpOVHL; 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 S231296AbhETH6l (ORCPT + 99 others); Thu, 20 May 2021 03:58:41 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52080 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231206AbhETH61 (ORCPT ); Thu, 20 May 2021 03:58:27 -0400 Received: from mail-qk1-x72d.google.com (mail-qk1-x72d.google.com [IPv6:2607:f8b0:4864:20::72d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7C0A6C061574; Thu, 20 May 2021 00:57:05 -0700 (PDT) Received: by mail-qk1-x72d.google.com with SMTP id x8so15314641qkl.2; Thu, 20 May 2021 00:57:05 -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=ulLpOVHLaTb/HRJes86S339F+nw8Eym6LA/wA40997o7iM/547d/NdYXSCd+UEil5m 5yYOkvh6keaGlZU1QnJnigVxiIZK9MwLJ+3OprrMFiomuY7wXoDZO1ERYn034L3VaqZ+ cdd3NfMMIRX8wlaDy9QcXncW2bS7qlsXrlnocOIafeTEWMpzbkV+oxOFLCH8CRx9dAlD 6X34XJKxEyhTrcMBUhB/kJGU+eBAN3tXRH8q4xe/xp5v/dhzIm/jVJkmcqV0eXjArgot ONNTk09uXUgBGgu8crPCClDB8K5sAie6ToWiyIQcpIMLg7cw7x8RoJ4EXceOXHpdmQH4 q/7w== 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=MD3vmVdP1kHXinI00jyFOnIvM0WVGkGIQ85zA/kkQ2DEetFW73YxC0oojX1CB9+2Gt PL0GGdOeXxEAaTkGJF3pQZ+TF0uJ5vINFnkX6OoR3BBQjXMeG86cCITG4SueCrmM6l45 DSVs9AnT66N3JFrIeFp0p6oVFcrpHpkacGYUZiIYWPUz5f+jlJSvA5lu32NQ+GNjxmo7 EfpcWIO/68MFfh+PXvbOLqDJVSIwPQccGEmqlqH8KWI8d415BRXio3BZSy8aWDtmjfnQ JgzYNj9/RQ5QrcutT5EWkfDYsibgip+Yd4Q1Gt88y/+CJsk6I1Ylr6WKK14EAyTWbdVF qFLQ== X-Gm-Message-State: AOAM533mS/vb7TKR0YtrG/yJ/OkUKAW+mUz7p0DsEPo1h2qknMJJK4KX /gKXBkVjTTzsCvbviCCf89A= X-Received: by 2002:a37:a48b:: with SMTP id n133mr3499357qke.90.1621497424632; Thu, 20 May 2021 00:57:04 -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 g9sm1478254qka.38.2021.05.20.00.57.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 May 2021 00:57:04 -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 v29 09/13] mm/damon/dbgfs: Support multiple contexts Date: Thu, 20 May 2021 07:56:25 +0000 Message-Id: <20210520075629.4332-10-sj38.park@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210520075629.4332-1-sj38.park@gmail.com> References: <20210520075629.4332-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