Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp1262842pxf; Fri, 26 Mar 2021 04:40:59 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzry+Gure6QzzpA2s3SCfh6jNuDpix2jJqcdsVwC6SZSv5Ve4jmRgeBXz2Q4QNzpESPqxAE X-Received: by 2002:a17:906:36d1:: with SMTP id b17mr3184264ejc.235.1616758859230; Fri, 26 Mar 2021 04:40:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1616758859; cv=none; d=google.com; s=arc-20160816; b=TUxNbD8RDOFuwOaflQUbfI6IOHmAnuuoix2dg6mUj2qWcuBG0vhnlbnkaSLyrvgqY0 zM2VelFnaBvQ0gfGPJJSzNcvYHKeEN3099lP7oPTwhHuatyqae70Simn+D5WCwlpMr/E eq3Rl4nyMPqzX2FvzluzEYlVnYcKe53VTZ1Ud0m84mFItceigBBhidz7UqGCnfCN2x9U e5+XYhLUdLdAMscLp78lqBRgeIGJ+rCZQAFQU7GmbNHrP72hK45EJ71WqvP2BSC/Xbtp GIBxV8s/l8bk7eLty1en/GxIDdCz0pbaD0jSFfV6cwBJndAEL2miU5WqsvkDih+Gio+H Ya3Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:in-reply-to:content-disposition:mime-version :references:message-id:subject:cc:to:from:date:dkim-signature; bh=mktisea4Z4cTtpOJLiT4dlCMI4XtzjXEktyvRdN2mvU=; b=zpXzalfmLF2LWO4FawL9shwaCjIUv9PTtVIqen0LVQmGu67U2lCsxGWf7nkD98ewWT CZkW2tyE68LPWAjLrBt5jrdaIeJXE8s/SjB5tFWOUhgFhW5SlgHl34iah8NWNqL1lwYC gE2BhTnu1IL+0fn5ckdhO7VnbHiphi1Uq55FgcSvK9ulMt4iCIPF0nS+ACFCP1uAK9Og +Nd0WS5m9Pgzs1RfZQaSkad1s268a2FLi6cL23DlS0vgugWkAUW6uTNR3C0JGCMqGv87 43pkdLTFI9pjidTPQYjnbFZVOpQ7pCbzH57OpjL6TQ30jlQakTEEYIqZlzN/eyUPVuPg E6yQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@infradead.org header.s=desiato.20200630 header.b=pQCprxJu; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id d24si6472863ejw.372.2021.03.26.04.40.35; Fri, 26 Mar 2021 04:40:59 -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=@infradead.org header.s=desiato.20200630 header.b=pQCprxJu; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229893AbhCZLj0 (ORCPT + 99 others); Fri, 26 Mar 2021 07:39:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42966 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229580AbhCZLi7 (ORCPT ); Fri, 26 Mar 2021 07:38:59 -0400 Received: from desiato.infradead.org (desiato.infradead.org [IPv6:2001:8b0:10b:1:d65d:64ff:fe57:4e05]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D9929C0613AA for ; Fri, 26 Mar 2021 04:38:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=In-Reply-To:Content-Type:MIME-Version: References:Message-ID:Subject:Cc:To:From:Date:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description; bh=mktisea4Z4cTtpOJLiT4dlCMI4XtzjXEktyvRdN2mvU=; b=pQCprxJu08+ESB6IPGA/KoPJMM cF6D+ya4mE+0MOjpYwr92AvUitw3B+QL1tLa/4rZ/pZac0l367Ycxe1swUqJjtfEjmthlMDCj27F1 /WP5nSJ0AvwTNv5bgmNJgAqOSgMyVurG97q7P+iiugLhgqYyRNBi4gS2aToQprlzlFqmwQ+GUWMT/ 8xUOkfvlfh4FFUNtw+RJFcQyXMdpTHSXwAaH6nm3p5fpDgWmNh5IOr1q+oUX2oJNskSz+csD2SEiP 7n8SCdDpKsGY+F4PtdTWqHETNOhG3+7qgFK9Mu7GWXMDc7/QKTcLJeQQqEG5dgvkh+NM2jZU1omMf HXITnxZg==; Received: from j217100.upc-j.chello.nl ([24.132.217.100] helo=noisy.programming.kicks-ass.net) by desiato.infradead.org with esmtpsa (Exim 4.94 #2 (Red Hat Linux)) id 1lPknY-003Rfb-Dt; Fri, 26 Mar 2021 11:38:40 +0000 Received: from hirez.programming.kicks-ass.net (hirez.programming.kicks-ass.net [192.168.1.225]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by noisy.programming.kicks-ass.net (Postfix) with ESMTPS id CC492306099; Fri, 26 Mar 2021 12:38:39 +0100 (CET) Received: by hirez.programming.kicks-ass.net (Postfix, from userid 1000) id 920CE2BD94356; Fri, 26 Mar 2021 12:38:39 +0100 (CET) Date: Fri, 26 Mar 2021 12:38:39 +0100 From: Peter Zijlstra To: Greg KH Cc: mingo@kernel.org, mgorman@suse.de, juri.lelli@redhat.com, vincent.guittot@linaro.org, dietmar.eggemann@arm.com, rostedt@goodmis.org, bsegall@google.com, bristot@redhat.com, joshdon@google.com, valentin.schneider@arm.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 6/9] debugfs: Implement debugfs_create_str() Message-ID: References: <20210326103352.603456266@infradead.org> <20210326103935.183934395@infradead.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Fri, Mar 26, 2021 at 12:30:24PM +0100, Greg KH wrote: > Great, change that and limit the size of the string that can be written > and it looks good to me, thanks for adding this. Here goes.. --- Subject: debugfs: Implement debugfs_create_str() From: Peter Zijlstra Date: Thu Mar 25 10:53:55 CET 2021 Implement debugfs_create_str() to easily display names and such in debugfs. Signed-off-by: Peter Zijlstra (Intel) --- fs/debugfs/file.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/debugfs.h | 27 ++++++++ 2 files changed, 175 insertions(+) --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -865,6 +865,154 @@ struct dentry *debugfs_create_bool(const } EXPORT_SYMBOL_GPL(debugfs_create_bool); +ssize_t debugfs_read_file_str(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct dentry *dentry = F_DENTRY(file); + char *str, *copy = NULL; + int copy_len, len; + ssize_t ret; + + ret = debugfs_file_get(dentry); + if (unlikely(ret)) + return ret; + +again: + rcu_read_lock(); + str = rcu_dereference(*(char **)file->private_data); + len = strlen(str) + 1; + + if (!copy || copy_len < len) { + rcu_read_unlock(); + kfree(copy); + copy = kmalloc(len + 1, GFP_KERNEL); + if (!copy) { + debugfs_file_put(dentry); + return -ENOMEM; + } + copy_len = len; + goto again; + } + + strncpy(copy, str, len); + copy[len] = '\n'; + copy[len+1] = '\0'; + rcu_read_unlock(); + + debugfs_file_put(dentry); + + ret = simple_read_from_buffer(user_buf, count, ppos, copy, len + 1); + kfree(copy); + + return ret; +} +EXPORT_SYMBOL_GPL(debugfs_read_file_str); + +ssize_t debugfs_write_file_str(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + 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 concattenation */ + 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; +} +EXPORT_SYMBOL_GPL(debugfs_write_file_str); + +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, +}; + +/** + * debugfs_create_str - create a debugfs file that is used to read and write a string value + * @name: a pointer to a string containing the name of the file to create. + * @mode: the permission that the file should have + * @parent: a pointer to the parent dentry for this file. This should be a + * directory dentry if set. If this parameter is %NULL, then the + * file will be created in the root of the debugfs filesystem. + * @value: a pointer to the variable that the file should read to and write + * from. + * + * This function creates a file in debugfs with the given name that + * contains the value of the variable @value. If the @mode variable is so + * set, it can be read from, and written to. + * + * This function will return a pointer to a dentry if it succeeds. This + * pointer must be passed to the debugfs_remove() function when the file is + * to be removed (no automatic cleanup happens if your module is unloaded, + * you are responsible here.) If an error occurs, ERR_PTR(-ERROR) will be + * returned. + * + * NOTE: when writing is enabled it will replace the string, string lifetime is + * assumed to be RCU managed. + * + * If debugfs is not enabled in the kernel, the value ERR_PTR(-ENODEV) will + * be returned. + */ +void debugfs_create_str(const char *name, umode_t mode, + struct dentry *parent, char **value) +{ + debugfs_create_mode_unsafe(name, mode, parent, value, &fops_str, + &fops_str_ro, &fops_str_wo); +} +EXPORT_SYMBOL_GPL(debugfs_create_str); + static ssize_t read_file_blob(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h @@ -128,6 +128,8 @@ void debugfs_create_atomic_t(const char struct dentry *parent, atomic_t *value); struct dentry *debugfs_create_bool(const char *name, umode_t mode, struct dentry *parent, bool *value); +void debugfs_create_str(const char *name, umode_t mode, + struct dentry *parent, char **value); struct dentry *debugfs_create_blob(const char *name, umode_t mode, struct dentry *parent, @@ -156,6 +158,12 @@ ssize_t debugfs_read_file_bool(struct fi ssize_t debugfs_write_file_bool(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos); +ssize_t debugfs_read_file_str(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos); + +ssize_t debugfs_write_file_str(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos); + #else #include @@ -297,6 +305,11 @@ static inline struct dentry *debugfs_cre return ERR_PTR(-ENODEV); } +static inline void debugfs_create_str(const char *name, umode_t mode, + struct dentry *parent, + char **value) +{ } + static inline struct dentry *debugfs_create_blob(const char *name, umode_t mode, struct dentry *parent, struct debugfs_blob_wrapper *blob) @@ -347,6 +360,20 @@ static inline ssize_t debugfs_write_file { return -ENODEV; } + +static inline ssize_t debugfs_read_file_str(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + return -ENODEV; +} + +static inline ssize_t debugfs_write_file_str(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + return -ENODEV; +} #endif