* [PATCH v3 0/3] Add interconnect debugfs client
@ 2023-08-07 14:29 Mike Tipton
2023-08-07 14:29 ` [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str() Mike Tipton
` (2 more replies)
0 siblings, 3 replies; 11+ messages in thread
From: Mike Tipton @ 2023-08-07 14:29 UTC (permalink / raw)
To: djakov, gregkh, rafael, corbet
Cc: linux-pm, linux-doc, linux-kernel, linux-arm-msm, quic_okukatla,
quic_viveka, peterz, quic_pkondeti, Mike Tipton
This series introduces interconnect debugfs files that support voting
for any path the framework supports.
We've historically relied on an out-of-tree module for this, which used
the old icc_get() that was recently removed in [0]. The old icc_get()
took integer endpoint IDs, which made identifying paths in our old
implementation non-intuitive. The logical node names typically don't
change much chip-to-chip, but the raw integer IDs do. Take this
opportunity to introduce an icc_get() that uses string names instead,
which allows for a more intuitive and generic debugfs interface.
We rely on this support for debug, test, and verification. Hopefully
it'll be useful for other vendors as well.
[0] commit 7dcdad6f32c9 ("interconnect: drop unused icc_get() interface")
Changes in v3:
- Use GFP_ATOMIC when allocating with the rcu lock held.
Changes in v2:
- Make icc_get() an internal interface.
- RCU-protect src_node and dst_node.
- Replace PLATFORM_DEVID_AUTO with PLATFORM_DEVID_NONE.
- Remove unnecessary #include.
- Add debugfs client documentation.
Mike Tipton (3):
debugfs: Add write support to debugfs_create_str()
interconnect: Reintroduce icc_get()
interconnect: Add debugfs test client
Documentation/driver-api/interconnect.rst | 25 ++++
drivers/interconnect/Makefile | 2 +-
drivers/interconnect/core.c | 66 +++++++++
drivers/interconnect/debugfs-client.c | 168 ++++++++++++++++++++++
drivers/interconnect/internal.h | 3 +
fs/debugfs/file.c | 48 ++++++-
6 files changed, 309 insertions(+), 3 deletions(-)
create mode 100644 drivers/interconnect/debugfs-client.c
--
2.17.1
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str()
2023-08-07 14:29 [PATCH v3 0/3] Add interconnect debugfs client Mike Tipton
@ 2023-08-07 14:29 ` Mike Tipton
2023-08-11 7:46 ` Georgi Djakov
2023-08-12 10:40 ` Greg KH
2023-08-07 14:29 ` [PATCH v3 2/3] interconnect: Reintroduce icc_get() Mike Tipton
2023-08-07 14:29 ` [PATCH v3 3/3] interconnect: Add debugfs test client Mike Tipton
2 siblings, 2 replies; 11+ messages in thread
From: Mike Tipton @ 2023-08-07 14:29 UTC (permalink / raw)
To: djakov, gregkh, rafael, corbet
Cc: linux-pm, linux-doc, linux-kernel, linux-arm-msm, quic_okukatla,
quic_viveka, peterz, quic_pkondeti, Mike Tipton
Currently, debugfs_create_str() only supports reading strings from
debugfs. Add support for writing them as well.
Based on original implementation by Peter Zijlstra [0]. Write support
was present in the initial patch version, but dropped in v2 due to lack
of users. We have a user now, so reintroduce it.
[0] https://lore.kernel.org/all/YF3Hv5zXb%2F6lauzs@hirez.programming.kicks-ass.net/
Signed-off-by: Mike Tipton <quic_mdtipton@quicinc.com>
---
fs/debugfs/file.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 46 insertions(+), 2 deletions(-)
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index b7711888dd17..87b3753aa4b1 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -904,8 +904,52 @@ EXPORT_SYMBOL_GPL(debugfs_create_str);
static ssize_t debugfs_write_file_str(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
{
- /* This is really only for read-only strings */
- return -EINVAL;
+ struct dentry *dentry = F_DENTRY(file);
+ char *old, *new = NULL;
+ int pos = *ppos;
+ int r;
+
+ r = debugfs_file_get(dentry);
+ if (unlikely(r))
+ return r;
+
+ old = *(char **)file->private_data;
+
+ /* only allow strict concatenation */
+ r = -EINVAL;
+ if (pos && pos != strlen(old))
+ goto error;
+
+ r = -E2BIG;
+ if (pos + count + 1 > PAGE_SIZE)
+ goto error;
+
+ r = -ENOMEM;
+ new = kmalloc(pos + count + 1, GFP_KERNEL);
+ if (!new)
+ goto error;
+
+ if (pos)
+ memcpy(new, old, pos);
+
+ r = -EFAULT;
+ if (copy_from_user(new + pos, user_buf, count))
+ goto error;
+
+ new[pos + count] = '\0';
+ strim(new);
+
+ rcu_assign_pointer(*(char **)file->private_data, new);
+ synchronize_rcu();
+ kfree(old);
+
+ debugfs_file_put(dentry);
+ return count;
+
+error:
+ kfree(new);
+ debugfs_file_put(dentry);
+ return r;
}
static const struct file_operations fops_str = {
--
2.17.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v3 2/3] interconnect: Reintroduce icc_get()
2023-08-07 14:29 [PATCH v3 0/3] Add interconnect debugfs client Mike Tipton
2023-08-07 14:29 ` [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str() Mike Tipton
@ 2023-08-07 14:29 ` Mike Tipton
2023-08-07 14:29 ` [PATCH v3 3/3] interconnect: Add debugfs test client Mike Tipton
2 siblings, 0 replies; 11+ messages in thread
From: Mike Tipton @ 2023-08-07 14:29 UTC (permalink / raw)
To: djakov, gregkh, rafael, corbet
Cc: linux-pm, linux-doc, linux-kernel, linux-arm-msm, quic_okukatla,
quic_viveka, peterz, quic_pkondeti, Mike Tipton
The original icc_get() that took integer node IDs was removed due to
lack of users. Reintroduce a new version that takes string node names,
which is needed for the debugfs client.
Signed-off-by: Mike Tipton <quic_mdtipton@quicinc.com>
---
drivers/interconnect/core.c | 63 +++++++++++++++++++++++++++++++++
drivers/interconnect/internal.h | 2 ++
2 files changed, 65 insertions(+)
diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c
index 5fac448c28fd..fc1461dfc61b 100644
--- a/drivers/interconnect/core.c
+++ b/drivers/interconnect/core.c
@@ -147,6 +147,21 @@ static struct icc_node *node_find(const int id)
return idr_find(&icc_idr, id);
}
+static struct icc_node *node_find_by_name(const char *name)
+{
+ struct icc_provider *provider;
+ struct icc_node *n;
+
+ list_for_each_entry(provider, &icc_providers, provider_list) {
+ list_for_each_entry(n, &provider->nodes, node_list) {
+ if (!strcmp(n->name, name))
+ return n;
+ }
+ }
+
+ return NULL;
+}
+
static struct icc_path *path_init(struct device *dev, struct icc_node *dst,
ssize_t num_nodes)
{
@@ -561,6 +576,54 @@ struct icc_path *of_icc_get(struct device *dev, const char *name)
}
EXPORT_SYMBOL_GPL(of_icc_get);
+/**
+ * icc_get() - get a path handle between two endpoints
+ * @dev: device pointer for the consumer device
+ * @src: source node name
+ * @dst: destination node name
+ *
+ * This function will search for a path between two endpoints and return an
+ * icc_path handle on success. Use icc_put() to release constraints when they
+ * are not needed anymore.
+ *
+ * Return: icc_path pointer on success or ERR_PTR() on error. NULL is returned
+ * when the API is disabled.
+ */
+struct icc_path *icc_get(struct device *dev, const char *src, const char *dst)
+{
+ struct icc_node *src_node, *dst_node;
+ struct icc_path *path = ERR_PTR(-EPROBE_DEFER);
+
+ mutex_lock(&icc_lock);
+
+ src_node = node_find_by_name(src);
+ if (!src_node) {
+ dev_err(dev, "%s: invalid src=%s\n", __func__, src);
+ goto out;
+ }
+
+ dst_node = node_find_by_name(dst);
+ if (!dst_node) {
+ dev_err(dev, "%s: invalid dst=%s\n", __func__, dst);
+ goto out;
+ }
+
+ path = path_find(dev, src_node, dst_node);
+ if (IS_ERR(path)) {
+ dev_err(dev, "%s: invalid path=%ld\n", __func__, PTR_ERR(path));
+ goto out;
+ }
+
+ path->name = kasprintf(GFP_KERNEL, "%s-%s", src_node->name, dst_node->name);
+ if (!path->name) {
+ kfree(path);
+ path = ERR_PTR(-ENOMEM);
+ }
+out:
+ mutex_unlock(&icc_lock);
+ return path;
+}
+
/**
* icc_set_tag() - set an optional tag on a path
* @path: the path we want to tag
diff --git a/drivers/interconnect/internal.h b/drivers/interconnect/internal.h
index f5f82a5c939e..95d6ba27bf78 100644
--- a/drivers/interconnect/internal.h
+++ b/drivers/interconnect/internal.h
@@ -41,4 +41,6 @@ struct icc_path {
struct icc_req reqs[];
};
+struct icc_path *icc_get(struct device *dev, const char *src, const char *dst);
+
#endif
--
2.17.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v3 3/3] interconnect: Add debugfs test client
2023-08-07 14:29 [PATCH v3 0/3] Add interconnect debugfs client Mike Tipton
2023-08-07 14:29 ` [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str() Mike Tipton
2023-08-07 14:29 ` [PATCH v3 2/3] interconnect: Reintroduce icc_get() Mike Tipton
@ 2023-08-07 14:29 ` Mike Tipton
2 siblings, 0 replies; 11+ messages in thread
From: Mike Tipton @ 2023-08-07 14:29 UTC (permalink / raw)
To: djakov, gregkh, rafael, corbet
Cc: linux-pm, linux-doc, linux-kernel, linux-arm-msm, quic_okukatla,
quic_viveka, peterz, quic_pkondeti, Mike Tipton
It's often useful during test, debug, and development to issue path
votes from shell. Add a debugfs client for this purpose.
Example usage:
cd /sys/kernel/debug/interconnect/test-client/
# Configure node endpoints for the path from CPU to DDR on
# qcom/sm8550.
echo chm_apps > src_node
echo ebi > dst_node
# Get path between src_node and dst_node. This is only
# necessary after updating the node endpoints.
echo 1 > get
# Set desired BW to 1GBps avg and 2GBps peak.
echo 1000000 > avg_bw
echo 2000000 > peak_bw
# Vote for avg_bw and peak_bw on the latest path from "get".
# Voting for multiple paths is possible by repeating this
# process for different nodes endpoints.
echo 1 > commit
Allowing userspace to directly enable and set bus rates can be dangerous
So, following in the footsteps of the regmap [0] and clk [1] frameworks,
keep these userspace controls compile-time disabled without Kconfig
options to enable them. Enabling this will require code changes to
define INTERCONNECT_ALLOW_WRITE_DEBUGFS.
[0] commit 09c6ecd39410 ("regmap: Add support for writing to regmap registers via debugfs")
[1] commit 37215da5553e ("clk: Add support for setting clk_rate via debugfs")
Signed-off-by: Mike Tipton <quic_mdtipton@quicinc.com>
---
Documentation/driver-api/interconnect.rst | 25 ++++
drivers/interconnect/Makefile | 2 +-
drivers/interconnect/core.c | 3 +
drivers/interconnect/debugfs-client.c | 168 ++++++++++++++++++++++
drivers/interconnect/internal.h | 1 +
5 files changed, 198 insertions(+), 1 deletion(-)
create mode 100644 drivers/interconnect/debugfs-client.c
diff --git a/Documentation/driver-api/interconnect.rst b/Documentation/driver-api/interconnect.rst
index 5ed4f57a6bac..a92d0f277a1f 100644
--- a/Documentation/driver-api/interconnect.rst
+++ b/Documentation/driver-api/interconnect.rst
@@ -113,3 +113,28 @@ through dot to generate diagrams in many graphical formats::
$ cat /sys/kernel/debug/interconnect/interconnect_graph | \
dot -Tsvg > interconnect_graph.svg
+
+The ``test-client`` directory provides interfaces for issuing BW requests to
+any arbitrary path. Note that for safety reasons, this feature is disabled by
+default without a Kconfig to enable it. Enabling it requires code changes to
+``#define INTERCONNECT_ALLOW_WRITE_DEBUGFS``. Example usage::
+
+ cd /sys/kernel/debug/interconnect/test-client/
+
+ # Configure node endpoints for the path from CPU to DDR on
+ # qcom/sm8550.
+ echo chm_apps > src_node
+ echo ebi > dst_node
+
+ # Get path between src_node and dst_node. This is only
+ # necessary after updating the node endpoints.
+ echo 1 > get
+
+ # Set desired BW to 1GBps avg and 2GBps peak.
+ echo 1000000 > avg_bw
+ echo 2000000 > peak_bw
+
+ # Vote for avg_bw and peak_bw on the latest path from "get".
+ # Voting for multiple paths is possible by repeating this
+ # process for different nodes endpoints.
+ echo 1 > commit
diff --git a/drivers/interconnect/Makefile b/drivers/interconnect/Makefile
index 5604ce351a9f..d0888babb9a1 100644
--- a/drivers/interconnect/Makefile
+++ b/drivers/interconnect/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
CFLAGS_core.o := -I$(src)
-icc-core-objs := core.o bulk.o
+icc-core-objs := core.o bulk.o debugfs-client.o
obj-$(CONFIG_INTERCONNECT) += icc-core.o
obj-$(CONFIG_INTERCONNECT_IMX) += imx/
diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c
index fc1461dfc61b..9e12bb5e523d 100644
--- a/drivers/interconnect/core.c
+++ b/drivers/interconnect/core.c
@@ -1116,6 +1116,9 @@ static int __init icc_init(void)
icc_debugfs_dir, NULL, &icc_summary_fops);
debugfs_create_file("interconnect_graph", 0444,
icc_debugfs_dir, NULL, &icc_graph_fops);
+
+ icc_debugfs_client_init(icc_debugfs_dir);
+
return 0;
}
diff --git a/drivers/interconnect/debugfs-client.c b/drivers/interconnect/debugfs-client.c
new file mode 100644
index 000000000000..bc3fd8a7b9eb
--- /dev/null
+++ b/drivers/interconnect/debugfs-client.c
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+#include <linux/debugfs.h>
+#include <linux/interconnect.h>
+#include <linux/platform_device.h>
+
+#include "internal.h"
+
+/*
+ * This can be dangerous, therefore don't provide any real compile time
+ * configuration option for this feature.
+ * People who want to use this will need to modify the source code directly.
+ */
+#undef INTERCONNECT_ALLOW_WRITE_DEBUGFS
+
+#if defined(INTERCONNECT_ALLOW_WRITE_DEBUGFS) && defined(CONFIG_DEBUG_FS)
+
+static LIST_HEAD(debugfs_paths);
+static DEFINE_MUTEX(debugfs_lock);
+
+static struct platform_device *pdev;
+static struct icc_path *cur_path;
+
+static char *src_node;
+static char *dst_node;
+static u32 avg_bw;
+static u32 peak_bw;
+static u32 tag;
+
+struct debugfs_path {
+ const char *src;
+ const char *dst;
+ struct icc_path *path;
+ struct list_head list;
+};
+
+static struct icc_path *get_path(const char *src, const char *dst)
+{
+ struct debugfs_path *path;
+
+ list_for_each_entry(path, &debugfs_paths, list) {
+ if (!strcmp(path->src, src) && !strcmp(path->dst, dst))
+ return path->path;
+ }
+
+ return NULL;
+}
+
+static int icc_get_set(void *data, u64 val)
+{
+ struct debugfs_path *debugfs_path;
+ char *src, *dst;
+ int ret = 0;
+
+ mutex_lock(&debugfs_lock);
+
+ rcu_read_lock();
+ src = rcu_dereference(src_node);
+ dst = rcu_dereference(dst_node);
+
+ /*
+ * If we've already looked up a path, then use the existing one instead
+ * of calling icc_get() again. This allows for updating previous BW
+ * votes when "get" is written to multiple times for multiple paths.
+ */
+ cur_path = get_path(src, dst);
+ if (cur_path) {
+ rcu_read_unlock();
+ goto out;
+ }
+
+ src = kstrdup(src, GFP_ATOMIC);
+ dst = kstrdup(dst, GFP_ATOMIC);
+ rcu_read_unlock();
+
+ if (!src || !dst) {
+ ret = -ENOMEM;
+ goto err_free;
+ }
+
+ cur_path = icc_get(&pdev->dev, src, dst);
+ if (IS_ERR(cur_path)) {
+ ret = PTR_ERR(cur_path);
+ goto err_free;
+ }
+
+ debugfs_path = kzalloc(sizeof(*debugfs_path), GFP_KERNEL);
+ if (!debugfs_path) {
+ ret = -ENOMEM;
+ goto err_put;
+ }
+
+ debugfs_path->path = cur_path;
+ debugfs_path->src = src;
+ debugfs_path->dst = dst;
+ list_add_tail(&debugfs_path->list, &debugfs_paths);
+
+ goto out;
+
+err_put:
+ icc_put(cur_path);
+err_free:
+ kfree(src);
+ kfree(dst);
+out:
+ mutex_unlock(&debugfs_lock);
+ return ret;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(icc_get_fops, NULL, icc_get_set, "%llu\n");
+
+static int icc_commit_set(void *data, u64 val)
+{
+ int ret;
+
+ mutex_lock(&debugfs_lock);
+
+ if (IS_ERR_OR_NULL(cur_path)) {
+ ret = PTR_ERR(cur_path);
+ goto out;
+ }
+
+ icc_set_tag(cur_path, tag);
+ ret = icc_set_bw(cur_path, avg_bw, peak_bw);
+out:
+ mutex_unlock(&debugfs_lock);
+ return ret;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(icc_commit_fops, NULL, icc_commit_set, "%llu\n");
+
+int icc_debugfs_client_init(struct dentry *icc_dir)
+{
+ struct dentry *client_dir;
+ int ret;
+
+ pdev = platform_device_alloc("icc-debugfs-client", PLATFORM_DEVID_NONE);
+
+ ret = platform_device_add(pdev);
+ if (ret) {
+ pr_err("%s: failed to add platform device: %d\n", __func__, ret);
+ platform_device_put(pdev);
+ return ret;
+ }
+
+ client_dir = debugfs_create_dir("test_client", icc_dir);
+
+ debugfs_create_str("src_node", 0600, client_dir, &src_node);
+ debugfs_create_str("dst_node", 0600, client_dir, &dst_node);
+ debugfs_create_file("get", 0200, client_dir, NULL, &icc_get_fops);
+ debugfs_create_u32("avg_bw", 0600, client_dir, &avg_bw);
+ debugfs_create_u32("peak_bw", 0600, client_dir, &peak_bw);
+ debugfs_create_u32("tag", 0600, client_dir, &tag);
+ debugfs_create_file("commit", 0200, client_dir, NULL, &icc_commit_fops);
+
+ return 0;
+}
+
+#else
+
+int icc_debugfs_client_init(struct dentry *icc_dir)
+{
+ return 0;
+}
+
+#endif
diff --git a/drivers/interconnect/internal.h b/drivers/interconnect/internal.h
index 95d6ba27bf78..3b2cfd32e449 100644
--- a/drivers/interconnect/internal.h
+++ b/drivers/interconnect/internal.h
@@ -42,5 +42,6 @@ struct icc_path {
};
struct icc_path *icc_get(struct device *dev, const char *src, const char *dst);
+int icc_debugfs_client_init(struct dentry *icc_dir);
#endif
--
2.17.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str()
2023-08-07 14:29 ` [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str() Mike Tipton
@ 2023-08-11 7:46 ` Georgi Djakov
2023-08-12 10:36 ` Greg KH
2023-08-12 10:40 ` Greg KH
1 sibling, 1 reply; 11+ messages in thread
From: Georgi Djakov @ 2023-08-11 7:46 UTC (permalink / raw)
To: Mike Tipton, gregkh, rafael, corbet
Cc: linux-pm, linux-doc, linux-kernel, linux-arm-msm, quic_okukatla,
quic_viveka, peterz, quic_pkondeti
On 7.08.23 17:29, Mike Tipton wrote:
> Currently, debugfs_create_str() only supports reading strings from
> debugfs. Add support for writing them as well.
>
> Based on original implementation by Peter Zijlstra [0]. Write support
> was present in the initial patch version, but dropped in v2 due to lack
> of users. We have a user now, so reintroduce it.
>
> [0] https://lore.kernel.org/all/YF3Hv5zXb%2F6lauzs@hirez.programming.kicks-ass.net/
>
Hi Greg,
Looks like the original code was reviewed two years ago (not sure if it
counts). But in any case, i need an ack from you to apply this.
There is no build dependency with the rest of the patches (but there is a
functional one). It should be also fine if you apply it directly, if you
prefer so?
Thanks,
Georgi
> Signed-off-by: Mike Tipton <quic_mdtipton@quicinc.com>
> ---
> fs/debugfs/file.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 46 insertions(+), 2 deletions(-)
>
> diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
> index b7711888dd17..87b3753aa4b1 100644
> --- a/fs/debugfs/file.c
> +++ b/fs/debugfs/file.c
> @@ -904,8 +904,52 @@ EXPORT_SYMBOL_GPL(debugfs_create_str);
> static ssize_t debugfs_write_file_str(struct file *file, const char __user *user_buf,
> size_t count, loff_t *ppos)
> {
> - /* This is really only for read-only strings */
> - return -EINVAL;
> + struct dentry *dentry = F_DENTRY(file);
> + char *old, *new = NULL;
> + int pos = *ppos;
> + int r;
> +
> + r = debugfs_file_get(dentry);
> + if (unlikely(r))
> + return r;
> +
> + old = *(char **)file->private_data;
> +
> + /* only allow strict concatenation */
> + r = -EINVAL;
> + if (pos && pos != strlen(old))
> + goto error;
> +
> + r = -E2BIG;
> + if (pos + count + 1 > PAGE_SIZE)
> + goto error;
> +
> + r = -ENOMEM;
> + new = kmalloc(pos + count + 1, GFP_KERNEL);
> + if (!new)
> + goto error;
> +
> + if (pos)
> + memcpy(new, old, pos);
> +
> + r = -EFAULT;
> + if (copy_from_user(new + pos, user_buf, count))
> + goto error;
> +
> + new[pos + count] = '\0';
> + strim(new);
> +
> + rcu_assign_pointer(*(char **)file->private_data, new);
> + synchronize_rcu();
> + kfree(old);
> +
> + debugfs_file_put(dentry);
> + return count;
> +
> +error:
> + kfree(new);
> + debugfs_file_put(dentry);
> + return r;
> }
>
> static const struct file_operations fops_str = {
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str()
2023-08-11 7:46 ` Georgi Djakov
@ 2023-08-12 10:36 ` Greg KH
2023-08-12 10:37 ` Greg KH
0 siblings, 1 reply; 11+ messages in thread
From: Greg KH @ 2023-08-12 10:36 UTC (permalink / raw)
To: Georgi Djakov
Cc: Mike Tipton, rafael, corbet, linux-pm, linux-doc, linux-kernel,
linux-arm-msm, quic_okukatla, quic_viveka, peterz, quic_pkondeti
On Fri, Aug 11, 2023 at 10:46:34AM +0300, Georgi Djakov wrote:
> On 7.08.23 17:29, Mike Tipton wrote:
> > Currently, debugfs_create_str() only supports reading strings from
> > debugfs. Add support for writing them as well.
> >
> > Based on original implementation by Peter Zijlstra [0]. Write support
> > was present in the initial patch version, but dropped in v2 due to lack
> > of users. We have a user now, so reintroduce it.
> >
> > [0] https://lore.kernel.org/all/YF3Hv5zXb%2F6lauzs@hirez.programming.kicks-ass.net/
> >
>
> Hi Greg,
>
> Looks like the original code was reviewed two years ago (not sure if it
> counts). But in any case, i need an ack from you to apply this.
>
> There is no build dependency with the rest of the patches (but there is a
> functional one). It should be also fine if you apply it directly, if you
> prefer so?
Feel free for this to go with the code that uses it:
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str()
2023-08-12 10:36 ` Greg KH
@ 2023-08-12 10:37 ` Greg KH
0 siblings, 0 replies; 11+ messages in thread
From: Greg KH @ 2023-08-12 10:37 UTC (permalink / raw)
To: Georgi Djakov
Cc: Mike Tipton, rafael, corbet, linux-pm, linux-doc, linux-kernel,
linux-arm-msm, quic_okukatla, quic_viveka, peterz, quic_pkondeti
On Sat, Aug 12, 2023 at 12:36:12PM +0200, Greg KH wrote:
> On Fri, Aug 11, 2023 at 10:46:34AM +0300, Georgi Djakov wrote:
> > On 7.08.23 17:29, Mike Tipton wrote:
> > > Currently, debugfs_create_str() only supports reading strings from
> > > debugfs. Add support for writing them as well.
> > >
> > > Based on original implementation by Peter Zijlstra [0]. Write support
> > > was present in the initial patch version, but dropped in v2 due to lack
> > > of users. We have a user now, so reintroduce it.
> > >
> > > [0] https://lore.kernel.org/all/YF3Hv5zXb%2F6lauzs@hirez.programming.kicks-ass.net/
> > >
> >
> > Hi Greg,
> >
> > Looks like the original code was reviewed two years ago (not sure if it
> > counts). But in any case, i need an ack from you to apply this.
> >
> > There is no build dependency with the rest of the patches (but there is a
> > functional one). It should be also fine if you apply it directly, if you
> > prefer so?
>
> Feel free for this to go with the code that uses it:
>
> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Wait, no, this isn't ok, this ACK is now rescinded:
NACKED-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str()
2023-08-07 14:29 ` [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str() Mike Tipton
2023-08-11 7:46 ` Georgi Djakov
@ 2023-08-12 10:40 ` Greg KH
2023-08-12 13:25 ` Georgi Djakov
2023-08-18 10:05 ` Georgi Djakov
1 sibling, 2 replies; 11+ messages in thread
From: Greg KH @ 2023-08-12 10:40 UTC (permalink / raw)
To: Mike Tipton
Cc: djakov, rafael, corbet, linux-pm, linux-doc, linux-kernel,
linux-arm-msm, quic_okukatla, quic_viveka, peterz, quic_pkondeti
On Mon, Aug 07, 2023 at 07:29:12AM -0700, Mike Tipton wrote:
> Currently, debugfs_create_str() only supports reading strings from
> debugfs. Add support for writing them as well.
>
> Based on original implementation by Peter Zijlstra [0]. Write support
> was present in the initial patch version, but dropped in v2 due to lack
> of users. We have a user now, so reintroduce it.
>
> [0] https://lore.kernel.org/all/YF3Hv5zXb%2F6lauzs@hirez.programming.kicks-ass.net/
>
> Signed-off-by: Mike Tipton <quic_mdtipton@quicinc.com>
> ---
> fs/debugfs/file.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 46 insertions(+), 2 deletions(-)
>
> diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
> index b7711888dd17..87b3753aa4b1 100644
> --- a/fs/debugfs/file.c
> +++ b/fs/debugfs/file.c
> @@ -904,8 +904,52 @@ EXPORT_SYMBOL_GPL(debugfs_create_str);
> static ssize_t debugfs_write_file_str(struct file *file, const char __user *user_buf,
> size_t count, loff_t *ppos)
> {
> - /* This is really only for read-only strings */
> - return -EINVAL;
> + struct dentry *dentry = F_DENTRY(file);
> + char *old, *new = NULL;
> + int pos = *ppos;
> + int r;
> +
> + r = debugfs_file_get(dentry);
> + if (unlikely(r))
> + return r;
> +
> + old = *(char **)file->private_data;
> +
> + /* only allow strict concatenation */
> + r = -EINVAL;
> + if (pos && pos != strlen(old))
> + goto error;
> +
> + r = -E2BIG;
> + if (pos + count + 1 > PAGE_SIZE)
> + goto error;
> +
> + r = -ENOMEM;
> + new = kmalloc(pos + count + 1, GFP_KERNEL);
> + if (!new)
> + goto error;
> +
> + if (pos)
> + memcpy(new, old, pos);
> +
> + r = -EFAULT;
> + if (copy_from_user(new + pos, user_buf, count))
> + goto error;
> +
> + new[pos + count] = '\0';
> + strim(new);
> +
> + rcu_assign_pointer(*(char **)file->private_data, new);
> + synchronize_rcu();
> + kfree(old);
> +
> + debugfs_file_put(dentry);
> + return count;
> +
> +error:
> + kfree(new);
> + debugfs_file_put(dentry);
> + return r;
> }
So you just added write support for ALL debugfs files that use the
string interface, what did you just allow to break?
I recommend just using your own debugfs file function instead, as this
could cause bad problems, right? Are you sure that all string calls can
handle the variable be freed underneath it like this call will allow to
happen?
So I wouldn't recommend doing this, sorry.
greg k-h
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str()
2023-08-12 10:40 ` Greg KH
@ 2023-08-12 13:25 ` Georgi Djakov
2023-08-18 10:05 ` Georgi Djakov
1 sibling, 0 replies; 11+ messages in thread
From: Georgi Djakov @ 2023-08-12 13:25 UTC (permalink / raw)
To: Greg KH, Mike Tipton
Cc: rafael, corbet, linux-pm, linux-doc, linux-kernel, linux-arm-msm,
quic_okukatla, quic_viveka, peterz, quic_pkondeti
Hi Greg,
Thanks for the comments!
On 12.08.23 13:40, Greg KH wrote:
> On Mon, Aug 07, 2023 at 07:29:12AM -0700, Mike Tipton wrote:
>> Currently, debugfs_create_str() only supports reading strings from
>> debugfs. Add support for writing them as well.
>>
>> Based on original implementation by Peter Zijlstra [0]. Write support
>> was present in the initial patch version, but dropped in v2 due to lack
>> of users. We have a user now, so reintroduce it.
>>
>> [0] https://lore.kernel.org/all/YF3Hv5zXb%2F6lauzs@hirez.programming.kicks-ass.net/
>>
>> Signed-off-by: Mike Tipton <quic_mdtipton@quicinc.com>
>> ---
>> fs/debugfs/file.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--
>> 1 file changed, 46 insertions(+), 2 deletions(-)
>>
>> diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
>> index b7711888dd17..87b3753aa4b1 100644
>> --- a/fs/debugfs/file.c
>> +++ b/fs/debugfs/file.c
>> @@ -904,8 +904,52 @@ EXPORT_SYMBOL_GPL(debugfs_create_str);
>> static ssize_t debugfs_write_file_str(struct file *file, const char __user *user_buf,
>> size_t count, loff_t *ppos)
>> {
>> - /* This is really only for read-only strings */
>> - return -EINVAL;
>> + struct dentry *dentry = F_DENTRY(file);
>> + char *old, *new = NULL;
>> + int pos = *ppos;
>> + int r;
>> +
>> + r = debugfs_file_get(dentry);
>> + if (unlikely(r))
>> + return r;
>> +
>> + old = *(char **)file->private_data;
>> +
>> + /* only allow strict concatenation */
>> + r = -EINVAL;
>> + if (pos && pos != strlen(old))
>> + goto error;
>> +
>> + r = -E2BIG;
>> + if (pos + count + 1 > PAGE_SIZE)
>> + goto error;
>> +
>> + r = -ENOMEM;
>> + new = kmalloc(pos + count + 1, GFP_KERNEL);
>> + if (!new)
>> + goto error;
>> +
>> + if (pos)
>> + memcpy(new, old, pos);
>> +
>> + r = -EFAULT;
>> + if (copy_from_user(new + pos, user_buf, count))
>> + goto error;
>> +
>> + new[pos + count] = '\0';
>> + strim(new);
>> +
>> + rcu_assign_pointer(*(char **)file->private_data, new);
>> + synchronize_rcu();
>> + kfree(old);
>> +
>> + debugfs_file_put(dentry);
>> + return count;
>> +
>> +error:
>> + kfree(new);
>> + debugfs_file_put(dentry);
>> + return r;
>> }
>
> So you just added write support for ALL debugfs files that use the
> string interface, what did you just allow to break?
Not really. According to the existing code, the write support for strings
is enabled only when the file is created with +w permissions. For read-only
files, we use fops_str_ro, which is the case for all existing string files:
$ git grep -w debugfs_create_str | egrep -v "fs/debugfs/file.c|include/linux/debugfs.h"
drivers/firmware/arm_scmi/driver.c: debugfs_create_str("instance_name", 0400, top_dentry,
drivers/firmware/arm_scmi/driver.c: debugfs_create_str("type", 0400, trans, (char **)&dbg->type);
drivers/opp/debugfs.c: debugfs_create_str("of_name", S_IRUGO, d, (char **)&opp->of_name);
For fops_str_ro, the .write function is not implemented, so nothing should break?
> I recommend just using your own debugfs file function instead, as this
> could cause bad problems, right?
Agree, and that should be exactly what this patch does.
> Are you sure that all string calls can
> handle the variable be freed underneath it like this call will allow to
> happen?
Looks fine, at least for this patch-set.
Thanks,
Georgi
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str()
2023-08-12 10:40 ` Greg KH
2023-08-12 13:25 ` Georgi Djakov
@ 2023-08-18 10:05 ` Georgi Djakov
2023-08-22 17:46 ` Greg KH
1 sibling, 1 reply; 11+ messages in thread
From: Georgi Djakov @ 2023-08-18 10:05 UTC (permalink / raw)
To: Greg KH, Mike Tipton
Cc: rafael, corbet, linux-pm, linux-doc, linux-kernel, linux-arm-msm,
quic_okukatla, quic_viveka, peterz, quic_pkondeti
Hi Greg,
On 12.08.23 13:40, Greg KH wrote:
> On Mon, Aug 07, 2023 at 07:29:12AM -0700, Mike Tipton wrote:
>> Currently, debugfs_create_str() only supports reading strings from
>> debugfs. Add support for writing them as well.
>>
>> Based on original implementation by Peter Zijlstra [0]. Write support
>> was present in the initial patch version, but dropped in v2 due to lack
>> of users. We have a user now, so reintroduce it.
>>
>> [0] https://lore.kernel.org/all/YF3Hv5zXb%2F6lauzs@hirez.programming.kicks-ass.net/
>>
>> Signed-off-by: Mike Tipton <quic_mdtipton@quicinc.com>
>> ---
>> fs/debugfs/file.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--
>> 1 file changed, 46 insertions(+), 2 deletions(-)
>>
>> diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
>> index b7711888dd17..87b3753aa4b1 100644
>> --- a/fs/debugfs/file.c
>> +++ b/fs/debugfs/file.c
>> @@ -904,8 +904,52 @@ EXPORT_SYMBOL_GPL(debugfs_create_str);
>> static ssize_t debugfs_write_file_str(struct file *file, const char __user *user_buf,
>> size_t count, loff_t *ppos)
>> {
>> - /* This is really only for read-only strings */
>> - return -EINVAL;
>> + struct dentry *dentry = F_DENTRY(file);
>> + char *old, *new = NULL;
>> + int pos = *ppos;
>> + int r;
>> +
>> + r = debugfs_file_get(dentry);
>> + if (unlikely(r))
>> + return r;
>> +
>> + old = *(char **)file->private_data;
>> +
>> + /* only allow strict concatenation */
>> + r = -EINVAL;
>> + if (pos && pos != strlen(old))
>> + goto error;
>> +
>> + r = -E2BIG;
>> + if (pos + count + 1 > PAGE_SIZE)
>> + goto error;
>> +
>> + r = -ENOMEM;
>> + new = kmalloc(pos + count + 1, GFP_KERNEL);
>> + if (!new)
>> + goto error;
>> +
>> + if (pos)
>> + memcpy(new, old, pos);
>> +
>> + r = -EFAULT;
>> + if (copy_from_user(new + pos, user_buf, count))
>> + goto error;
>> +
>> + new[pos + count] = '\0';
>> + strim(new);
>> +
>> + rcu_assign_pointer(*(char **)file->private_data, new);
>> + synchronize_rcu();
>> + kfree(old);
>> +
>> + debugfs_file_put(dentry);
>> + return count;
>> +
>> +error:
>> + kfree(new);
>> + debugfs_file_put(dentry);
>> + return r;
>> }
>
> So you just added write support for ALL debugfs files that use the
> string interface, what did you just allow to break?
Not true. Write support is added only for debugfs string files that are
created with +w permissions. All existing files are created as read-only
and use the fops_str_ro ops.
> I recommend just using your own debugfs file function instead, as this
> could cause bad problems, right? Are you sure that all string calls can
> handle the variable be freed underneath it like this call will allow to
> happen?
>
> So I wouldn't recommend doing this, sorry.
>
Maybe you missed the fact that the different file ops are already there
and are selected based on permissions:
> static const struct file_operations fops_str = {
> .read = debugfs_read_file_str,
> .write = debugfs_write_file_str,
> .open = simple_open,
> .llseek = default_llseek,
> };
>
> static const struct file_operations fops_str_ro = {
> .read = debugfs_read_file_str,
> .open = simple_open,
> .llseek = default_llseek,
> };
>
> static const struct file_operations fops_str_wo = {
> .write = debugfs_write_file_str,
> .open = simple_open,
> .llseek = default_llseek,
> };
...so this patch is doing exactly what you suggested? If you agree,
could you ack it again please?
Thanks,
Georgi
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str()
2023-08-18 10:05 ` Georgi Djakov
@ 2023-08-22 17:46 ` Greg KH
0 siblings, 0 replies; 11+ messages in thread
From: Greg KH @ 2023-08-22 17:46 UTC (permalink / raw)
To: Georgi Djakov
Cc: Mike Tipton, rafael, corbet, linux-pm, linux-doc, linux-kernel,
linux-arm-msm, quic_okukatla, quic_viveka, peterz, quic_pkondeti
On Fri, Aug 18, 2023 at 01:05:57PM +0300, Georgi Djakov wrote:
> Hi Greg,
>
> On 12.08.23 13:40, Greg KH wrote:
> > On Mon, Aug 07, 2023 at 07:29:12AM -0700, Mike Tipton wrote:
> > > Currently, debugfs_create_str() only supports reading strings from
> > > debugfs. Add support for writing them as well.
> > >
> > > Based on original implementation by Peter Zijlstra [0]. Write support
> > > was present in the initial patch version, but dropped in v2 due to lack
> > > of users. We have a user now, so reintroduce it.
> > >
> > > [0] https://lore.kernel.org/all/YF3Hv5zXb%2F6lauzs@hirez.programming.kicks-ass.net/
> > >
> > > Signed-off-by: Mike Tipton <quic_mdtipton@quicinc.com>
> > > ---
> > > fs/debugfs/file.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--
> > > 1 file changed, 46 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
> > > index b7711888dd17..87b3753aa4b1 100644
> > > --- a/fs/debugfs/file.c
> > > +++ b/fs/debugfs/file.c
> > > @@ -904,8 +904,52 @@ EXPORT_SYMBOL_GPL(debugfs_create_str);
> > > static ssize_t debugfs_write_file_str(struct file *file, const char __user *user_buf,
> > > size_t count, loff_t *ppos)
> > > {
> > > - /* This is really only for read-only strings */
> > > - return -EINVAL;
> > > + struct dentry *dentry = F_DENTRY(file);
> > > + char *old, *new = NULL;
> > > + int pos = *ppos;
> > > + int r;
> > > +
> > > + r = debugfs_file_get(dentry);
> > > + if (unlikely(r))
> > > + return r;
> > > +
> > > + old = *(char **)file->private_data;
> > > +
> > > + /* only allow strict concatenation */
> > > + r = -EINVAL;
> > > + if (pos && pos != strlen(old))
> > > + goto error;
> > > +
> > > + r = -E2BIG;
> > > + if (pos + count + 1 > PAGE_SIZE)
> > > + goto error;
> > > +
> > > + r = -ENOMEM;
> > > + new = kmalloc(pos + count + 1, GFP_KERNEL);
> > > + if (!new)
> > > + goto error;
> > > +
> > > + if (pos)
> > > + memcpy(new, old, pos);
> > > +
> > > + r = -EFAULT;
> > > + if (copy_from_user(new + pos, user_buf, count))
> > > + goto error;
> > > +
> > > + new[pos + count] = '\0';
> > > + strim(new);
> > > +
> > > + rcu_assign_pointer(*(char **)file->private_data, new);
> > > + synchronize_rcu();
> > > + kfree(old);
> > > +
> > > + debugfs_file_put(dentry);
> > > + return count;
> > > +
> > > +error:
> > > + kfree(new);
> > > + debugfs_file_put(dentry);
> > > + return r;
> > > }
> >
> > So you just added write support for ALL debugfs files that use the
> > string interface, what did you just allow to break?
>
> Not true. Write support is added only for debugfs string files that are
> created with +w permissions. All existing files are created as read-only
> and use the fops_str_ro ops.
>
> > I recommend just using your own debugfs file function instead, as this
> > could cause bad problems, right? Are you sure that all string calls can
> > handle the variable be freed underneath it like this call will allow to
> > happen?
> >
> > So I wouldn't recommend doing this, sorry.
> >
>
> Maybe you missed the fact that the different file ops are already there
> and are selected based on permissions:
>
> > static const struct file_operations fops_str = {
> > .read = debugfs_read_file_str,
> > .write = debugfs_write_file_str,
> > .open = simple_open,
> > .llseek = default_llseek,
> > };
> >
> > static const struct file_operations fops_str_ro = {
> > .read = debugfs_read_file_str,
> > .open = simple_open,
> > .llseek = default_llseek,
> > };
> >
> > static const struct file_operations fops_str_wo = {
> > .write = debugfs_write_file_str,
> > .open = simple_open,
> > .llseek = default_llseek,
> > };
>
> ...so this patch is doing exactly what you suggested? If you agree,
> could you ack it again please?
Yes, I did miss that, sorry, my appologies for dragging this out so
long:
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2023-08-22 17:46 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-08-07 14:29 [PATCH v3 0/3] Add interconnect debugfs client Mike Tipton
2023-08-07 14:29 ` [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str() Mike Tipton
2023-08-11 7:46 ` Georgi Djakov
2023-08-12 10:36 ` Greg KH
2023-08-12 10:37 ` Greg KH
2023-08-12 10:40 ` Greg KH
2023-08-12 13:25 ` Georgi Djakov
2023-08-18 10:05 ` Georgi Djakov
2023-08-22 17:46 ` Greg KH
2023-08-07 14:29 ` [PATCH v3 2/3] interconnect: Reintroduce icc_get() Mike Tipton
2023-08-07 14:29 ` [PATCH v3 3/3] interconnect: Add debugfs test client Mike Tipton
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).