Received: by 2002:a05:6a10:206:0:0:0:0 with SMTP id 6csp3571691pxj; Mon, 21 Jun 2021 01:34:04 -0700 (PDT) X-Google-Smtp-Source: ABdhPJx+R0DDXM75x4srN+X09PbsoH1/rfkfADScCz1yU2Jaxxw2qJG7CCBaj4u/w3PGj3Zsaf/M X-Received: by 2002:a5d:974f:: with SMTP id c15mr16622862ioo.190.1624264444693; Mon, 21 Jun 2021 01:34:04 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1624264444; cv=none; d=google.com; s=arc-20160816; b=Kmjucm1SR7xT5oy7EXctl3OhZEVTefEJbw9ZBlyEMinmy9ABm4qxAFe/o0Qfsb2LYt gMSSssCeMVs0uQ93FSRobjxzodLuNDAJgBJPNTO379/WwxR1vgDCL9RT8NHRkH5n1fom L2SqazfOZPgvdnuCvU1ZPZ/d/6Duve/jlHQGzOoZI6SAywJ9AS2pCYdg2V3FXtjigqlE D9FboY2oyEk1rG1KTekLQpQmTENqRn7hUIHZaXOP+1inTxUL6/G5Zoh/L269BaNwSamO Oow5BaevNqufGgNdVrRXuGVi8S0GsfrXDuEqYIdERWp+0j8deRNwE9QW/Hpt/nvirTZw ALpA== 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=kqlHkD/PLSUy6nhF4tYtgJUa30ZRciHV+kTmSL6mehc=; b=RxfvBf3qPJV7+cnPpiq2HJKLRhx0hvY7KNSZpOVR1QaecCNhTR0vm8uGqAP72+C/iW vpc2LZQXICx/vK8F8DVjAdd4gj/l5Q0OOY7OmiB7yPVKORb3Ce0CZEJwJPW+pan7cjeh SWYoQzhFk0Fmq0SzkSpMw5RNHNGrINHoUUpy/y9y+TCK0osWUYCzBV2x+SLAOrGktVAS /o9Z6Evpv21yDMt81vMjOYAayUuKvOtlr1ezVvLMRHJlnLnmBHouAMuLtcPh19rTZstA okPo69/qLyGNiHLP9bczXW4dSEtm1pC6zUj9oyEYsNiLTbt03RZWVlBSzmzLjynyemxt 7GhA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b="HC/Knfdf"; 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 z4si19014473jat.36.2021.06.21.01.33.53; Mon, 21 Jun 2021 01:34:04 -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="HC/Knfdf"; 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 S231147AbhFUIeS (ORCPT + 99 others); Mon, 21 Jun 2021 04:34:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33344 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230381AbhFUIeF (ORCPT ); Mon, 21 Jun 2021 04:34:05 -0400 Received: from mail-qt1-x82b.google.com (mail-qt1-x82b.google.com [IPv6:2607:f8b0:4864:20::82b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 50D8EC061756; Mon, 21 Jun 2021 01:31:50 -0700 (PDT) Received: by mail-qt1-x82b.google.com with SMTP id z4so12831162qts.4; Mon, 21 Jun 2021 01:31:50 -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=kqlHkD/PLSUy6nhF4tYtgJUa30ZRciHV+kTmSL6mehc=; b=HC/Knfdf+QSz5LsWZ6EGNeVva8zxMyEbo3+QgFPB6NLqxXsOU9ETFom9G7Q0k6Ro8K I7fOLlSMRj7UkeCRG2RlyBG6dhvpE/5KXJzcj/RqPqsVvPChK/FSpcePcwP4K6GtdKX0 d+rl8PxHDm2jzxA8AYJ1p09avqhh9t8QBQ4HDgebQQcFyxGJIFZC8CveAdPnkbyz+4Bv e77Vr5NntdEnUPnHcNKBxD8fav0VoZMJulz51gUatOf9OVZgFxggPJiaZ3kh5GVXFOVa 3yV2wR7OrqN6+uYSJ6AaKAGP/DKlVqwSsYLsm8SkaW2Y+jJm7s5232s0kBtTFDB3xZNr fVvQ== 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=kqlHkD/PLSUy6nhF4tYtgJUa30ZRciHV+kTmSL6mehc=; b=Zp8aGqOTTO+9nnIkn6G0AxNk+bXSQtXvy4tCnSV2cESSHFLi5ElyEOLPgXHDGSJ5As 1hHVgxDhWQb9co4/4ADfvIf0IM/i1ULdwKzg7TVV5voG/j9ZuPrTcrkrM7B4NWVqqEg8 I7g2B0ejRJNdUwKpk88PrayCsShltvM3KSqWbI0gqiG+q/VR07SL8503EM79E1yNcDWT ZH0XU8XNAy+QOPb5oj79jgkqZcCmn504YqWcK0bANkxvuLK4+OxM4nnkOaLR2Om9Cktu nZcySfmZBpkl2XVaaju0P54nqVfnHRQWV5n8dt+l3eqD99NP8CWP6z1rTdUEIs9l4XYi 7jMw== X-Gm-Message-State: AOAM532uMNv1Fd9W5W5xiHjr/plnJcbtSngLQ4iWOnFvy850HOzk/Ce4 He3cvOeDtYhDSVtW1ahJWA8= X-Received: by 2002:a05:622a:89:: with SMTP id o9mr22149300qtw.339.1624264309495; Mon, 21 Jun 2021 01:31:49 -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 l23sm9852581qtp.28.2021.06.21.01.31.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Jun 2021 01:31:49 -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, jgowans@amazon.com, mgorman@suse.de, mheyne@amazon.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, sieberf@amazon.com, sj38.park@gmail.com, snu@zelle79.org, 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 v31 09/13] mm/damon/dbgfs: Support multiple contexts Date: Mon, 21 Jun 2021 08:31:04 +0000 Message-Id: <20210621083108.17589-10-sj38.park@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210621083108.17589-1-sj38.park@gmail.com> References: <20210621083108.17589-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 Reviewed-by: Fernand Sieber --- 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 524362f8c628..07bc03f7f34d 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, negative 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