mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-08-15 15:09:17 +00:00

Existing primitive has several problems: 1) calling conventions are clumsy - it returns a dentry reference that is either identical to its second argument or is an ERR_PTR(-E...); in both cases no refcount changes happen. Inconvenient for users and bug-prone; it would be better to have it return 0 on success and -E... on failure. 2) it allows cross-directory moves; however, no such caller have ever materialized and considering the way debugfs is used, it's unlikely to happen in the future. What's more, any such caller would have fun issues to deal with wrt interplay with recursive removal. It also makes the calling conventions clumsier... 3) tautological rename fails; the callers have no race-free way to deal with that. 4) new name must have been formed by the caller; quite a few callers have it done by sprintf/kasprintf/etc., ending up with considerable boilerplate. Proposed replacement: int debugfs_change_name(dentry, fmt, ...). All callers convert to that easily, and it's simpler internally. IMO debugfs_rename() should go; if we ever get a real-world use case for cross-directory moves in debugfs, we can always look into the right way to handle that. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Link: https://lore.kernel.org/r/20250112080705.141166-21-viro@zeniv.linux.org.uk Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
124 lines
3.2 KiB
C
124 lines
3.2 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* debugfs code for HSR & PRP
|
|
* Copyright (C) 2019 Texas Instruments Incorporated
|
|
*
|
|
* Author(s):
|
|
* Murali Karicheri <m-karicheri2@ti.com>
|
|
*/
|
|
#include <linux/module.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/debugfs.h>
|
|
#include "hsr_main.h"
|
|
#include "hsr_framereg.h"
|
|
|
|
static struct dentry *hsr_debugfs_root_dir;
|
|
|
|
/* hsr_node_table_show - Formats and prints node_table entries */
|
|
static int
|
|
hsr_node_table_show(struct seq_file *sfp, void *data)
|
|
{
|
|
struct hsr_priv *priv = (struct hsr_priv *)sfp->private;
|
|
struct hsr_node *node;
|
|
|
|
seq_printf(sfp, "Node Table entries for (%s) device\n",
|
|
(priv->prot_version == PRP_V1 ? "PRP" : "HSR"));
|
|
seq_puts(sfp, "MAC-Address-A, MAC-Address-B, time_in[A], ");
|
|
seq_puts(sfp, "time_in[B], Address-B port, ");
|
|
if (priv->prot_version == PRP_V1)
|
|
seq_puts(sfp, "SAN-A, SAN-B, DAN-P\n");
|
|
else
|
|
seq_puts(sfp, "DAN-H\n");
|
|
|
|
rcu_read_lock();
|
|
list_for_each_entry_rcu(node, &priv->node_db, mac_list) {
|
|
/* skip self node */
|
|
if (hsr_addr_is_self(priv, node->macaddress_A))
|
|
continue;
|
|
seq_printf(sfp, "%pM ", &node->macaddress_A[0]);
|
|
seq_printf(sfp, "%pM ", &node->macaddress_B[0]);
|
|
seq_printf(sfp, "%10lx, ", node->time_in[HSR_PT_SLAVE_A]);
|
|
seq_printf(sfp, "%10lx, ", node->time_in[HSR_PT_SLAVE_B]);
|
|
seq_printf(sfp, "%14x, ", node->addr_B_port);
|
|
|
|
if (priv->prot_version == PRP_V1)
|
|
seq_printf(sfp, "%5x, %5x, %5x\n",
|
|
node->san_a, node->san_b,
|
|
(node->san_a == 0 && node->san_b == 0));
|
|
else
|
|
seq_printf(sfp, "%5x\n", 1);
|
|
}
|
|
rcu_read_unlock();
|
|
return 0;
|
|
}
|
|
|
|
DEFINE_SHOW_ATTRIBUTE(hsr_node_table);
|
|
|
|
void hsr_debugfs_rename(struct net_device *dev)
|
|
{
|
|
struct hsr_priv *priv = netdev_priv(dev);
|
|
int err;
|
|
|
|
err = debugfs_change_name(priv->node_tbl_root, "%s", dev->name);
|
|
if (err)
|
|
netdev_warn(dev, "failed to rename\n");
|
|
}
|
|
|
|
/* hsr_debugfs_init - create hsr node_table file for dumping
|
|
* the node table
|
|
*
|
|
* Description:
|
|
* When debugfs is configured this routine sets up the node_table file per
|
|
* hsr device for dumping the node_table entries
|
|
*/
|
|
void hsr_debugfs_init(struct hsr_priv *priv, struct net_device *hsr_dev)
|
|
{
|
|
struct dentry *de = NULL;
|
|
|
|
de = debugfs_create_dir(hsr_dev->name, hsr_debugfs_root_dir);
|
|
if (IS_ERR(de)) {
|
|
pr_err("Cannot create hsr debugfs directory\n");
|
|
return;
|
|
}
|
|
|
|
priv->node_tbl_root = de;
|
|
|
|
de = debugfs_create_file("node_table", S_IFREG | 0444,
|
|
priv->node_tbl_root, priv,
|
|
&hsr_node_table_fops);
|
|
if (IS_ERR(de)) {
|
|
pr_err("Cannot create hsr node_table file\n");
|
|
debugfs_remove(priv->node_tbl_root);
|
|
priv->node_tbl_root = NULL;
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* hsr_debugfs_term - Tear down debugfs intrastructure
|
|
*
|
|
* Description:
|
|
* When Debugfs is configured this routine removes debugfs file system
|
|
* elements that are specific to hsr
|
|
*/
|
|
void
|
|
hsr_debugfs_term(struct hsr_priv *priv)
|
|
{
|
|
debugfs_remove_recursive(priv->node_tbl_root);
|
|
priv->node_tbl_root = NULL;
|
|
}
|
|
|
|
void hsr_debugfs_create_root(void)
|
|
{
|
|
hsr_debugfs_root_dir = debugfs_create_dir("hsr", NULL);
|
|
if (IS_ERR(hsr_debugfs_root_dir)) {
|
|
pr_err("Cannot create hsr debugfs root directory\n");
|
|
hsr_debugfs_root_dir = NULL;
|
|
}
|
|
}
|
|
|
|
void hsr_debugfs_remove_root(void)
|
|
{
|
|
/* debugfs_remove() internally checks NULL and ERROR */
|
|
debugfs_remove(hsr_debugfs_root_dir);
|
|
}
|