Re: [PATCH] NTB: ntb_transport: Use seq_file for QP stats debugfs
Koichiro Den <[email protected]>
| Newsgroups | dev.linux.lists.ntb,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <xvvxd2znh4oevszatoonpefnggg5ujknx4phy667vzrevmztmi@t2swaz73yhdm> |
On Tue, Jan 06, 2026 at 09:37:06AM -0700, Dave Jiang wrote: > > > On 12/17/25 1:19 AM, Koichiro Den wrote: > > The ./qp*/stats debugfs file for each NTB transport QP is currently > > implemented with a hand-crafted kmalloc() buffer and a series of > > scnprintf() calls. This is a pre-seq_file style pattern and makes future > > extensions easy to truncate. > > > > Convert the stats file to use the seq_file helpers via > > DEFINE_SHOW_ATTRIBUTE(), which simplifies the code and lets the seq_file > > core handle buffering and partial reads. > > > > While touching this area, fix a bug in the per-QP debugfs directory > > naming: the buffer used for "qp%d" was only 4 bytes, which truncates > > names like "qp10" to "qp1" and causes multiple queues to share the same > > directory. Enlarge the buffer and use sizeof() to avoid truncation. > > > > Reviewed-by: Frank Li <[email protected]> > > Signed-off-by: Koichiro Den <[email protected]> > > Reviewed-by: Dave Jiang <[email protected]> > > Thanks for the improvement! > > Can you please split out the bug fix and add a Fixes tag so it can go to stable kernels? Thanks! I have split it out and sent v2 here: https://lore.kernel.org/all/[email protected]/ Thanks for the review, Koichiro > > > --- > > Note: This patch is split out from the following series, where it was > > originally included as a preparatory change (refactor + small fix): > > https://lore.kernel.org/all/aS3xe0CNHeIMUu7P@lizhi-Precision-Tower-5810/ > > --- > > drivers/ntb/ntb_transport.c | 136 +++++++++++------------------------- > > 1 file changed, 41 insertions(+), 95 deletions(-) > > > > diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c > > index eb875e3db2e3..d5a544bf8fd6 100644 > > --- a/drivers/ntb/ntb_transport.c > > +++ b/drivers/ntb/ntb_transport.c > > @@ -57,6 +57,7 @@ > > #include <linux/module.h> > > #include <linux/pci.h> > > #include <linux/slab.h> > > +#include <linux/seq_file.h> > > #include <linux/types.h> > > #include <linux/uaccess.h> > > #include <linux/mutex.h> > > @@ -466,104 +467,49 @@ void ntb_transport_unregister_client(struct ntb_transport_client *drv) > > } > > EXPORT_SYMBOL_GPL(ntb_transport_unregister_client); > > > > -static ssize_t debugfs_read(struct file *filp, char __user *ubuf, size_t count, > > - loff_t *offp) > > +static int ntb_qp_debugfs_stats_show(struct seq_file *s, void *v) > > { > > - struct ntb_transport_qp *qp; > > - char *buf; > > - ssize_t ret, out_offset, out_count; > > - > > - qp = filp->private_data; > > + struct ntb_transport_qp *qp = s->private; > > > > if (!qp || !qp->link_is_up) > > return 0; > > > > - out_count = 1000; > > - > > - buf = kmalloc(out_count, GFP_KERNEL); > > - if (!buf) > > - return -ENOMEM; > > + seq_puts(s, "\nNTB QP stats:\n\n"); > > + > > + seq_printf(s, "rx_bytes - \t%llu\n", qp->rx_bytes); > > + seq_printf(s, "rx_pkts - \t%llu\n", qp->rx_pkts); > > + seq_printf(s, "rx_memcpy - \t%llu\n", qp->rx_memcpy); > > + seq_printf(s, "rx_async - \t%llu\n", qp->rx_async); > > + seq_printf(s, "rx_ring_empty - %llu\n", qp->rx_ring_empty); > > + seq_printf(s, "rx_err_no_buf - %llu\n", qp->rx_err_no_buf); > > + seq_printf(s, "rx_err_oflow - \t%llu\n", qp->rx_err_oflow); > > + seq_printf(s, "rx_err_ver - \t%llu\n", qp->rx_err_ver); > > + seq_printf(s, "rx_buff - \t0x%p\n", qp->rx_buff); > > + seq_printf(s, "rx_index - \t%u\n", qp->rx_index); > > + seq_printf(s, "rx_max_entry - \t%u\n", qp->rx_max_entry); > > + seq_printf(s, "rx_alloc_entry - \t%u\n\n", qp->rx_alloc_entry); > > + > > + seq_printf(s, "tx_bytes - \t%llu\n", qp->tx_bytes); > > + seq_printf(s, "tx_pkts - \t%llu\n", qp->tx_pkts); > > + seq_printf(s, "tx_memcpy - \t%llu\n", qp->tx_memcpy); > > + seq_printf(s, "tx_async - \t%llu\n", qp->tx_async); > > + seq_printf(s, "tx_ring_full - \t%llu\n", qp->tx_ring_full); > > + seq_printf(s, "tx_err_no_buf - %llu\n", qp->tx_err_no_buf); > > + seq_printf(s, "tx_mw - \t0x%p\n", qp->tx_mw); > > + seq_printf(s, "tx_index (H) - \t%u\n", qp->tx_index); > > + seq_printf(s, "RRI (T) - \t%u\n", qp->remote_rx_info->entry); > > + seq_printf(s, "tx_max_entry - \t%u\n", qp->tx_max_entry); > > + seq_printf(s, "free tx - \t%u\n", ntb_transport_tx_free_entry(qp)); > > + seq_putc(s, '\n'); > > + > > + seq_printf(s, "Using TX DMA - \t%s\n", qp->tx_dma_chan ? "Yes" : "No"); > > + seq_printf(s, "Using RX DMA - \t%s\n", qp->rx_dma_chan ? "Yes" : "No"); > > + seq_printf(s, "QP Link - \t%s\n", qp->link_is_up ? "Up" : "Down"); > > + seq_putc(s, '\n'); > > > > - out_offset = 0; > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "\nNTB QP stats:\n\n"); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "rx_bytes - \t%llu\n", qp->rx_bytes); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "rx_pkts - \t%llu\n", qp->rx_pkts); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "rx_memcpy - \t%llu\n", qp->rx_memcpy); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "rx_async - \t%llu\n", qp->rx_async); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "rx_ring_empty - %llu\n", qp->rx_ring_empty); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "rx_err_no_buf - %llu\n", qp->rx_err_no_buf); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "rx_err_oflow - \t%llu\n", qp->rx_err_oflow); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "rx_err_ver - \t%llu\n", qp->rx_err_ver); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "rx_buff - \t0x%p\n", qp->rx_buff); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "rx_index - \t%u\n", qp->rx_index); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "rx_max_entry - \t%u\n", qp->rx_max_entry); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "rx_alloc_entry - \t%u\n\n", qp->rx_alloc_entry); > > - > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "tx_bytes - \t%llu\n", qp->tx_bytes); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "tx_pkts - \t%llu\n", qp->tx_pkts); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "tx_memcpy - \t%llu\n", qp->tx_memcpy); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "tx_async - \t%llu\n", qp->tx_async); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "tx_ring_full - \t%llu\n", qp->tx_ring_full); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "tx_err_no_buf - %llu\n", qp->tx_err_no_buf); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "tx_mw - \t0x%p\n", qp->tx_mw); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "tx_index (H) - \t%u\n", qp->tx_index); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "RRI (T) - \t%u\n", > > - qp->remote_rx_info->entry); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "tx_max_entry - \t%u\n", qp->tx_max_entry); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "free tx - \t%u\n", > > - ntb_transport_tx_free_entry(qp)); > > - > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "\n"); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "Using TX DMA - \t%s\n", > > - qp->tx_dma_chan ? "Yes" : "No"); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "Using RX DMA - \t%s\n", > > - qp->rx_dma_chan ? "Yes" : "No"); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "QP Link - \t%s\n", > > - qp->link_is_up ? "Up" : "Down"); > > - out_offset += scnprintf(buf + out_offset, out_count - out_offset, > > - "\n"); > > - > > - if (out_offset > out_count) > > - out_offset = out_count; > > - > > - ret = simple_read_from_buffer(ubuf, count, offp, buf, out_offset); > > - kfree(buf); > > - return ret; > > -} > > - > > -static const struct file_operations ntb_qp_debugfs_stats = { > > - .owner = THIS_MODULE, > > - .open = simple_open, > > - .read = debugfs_read, > > -}; > > + return 0; > > +} > > +DEFINE_SHOW_ATTRIBUTE(ntb_qp_debugfs_stats); > > > > static void ntb_list_add(spinlock_t *lock, struct list_head *entry, > > struct list_head *list) > > @@ -1236,15 +1182,15 @@ static int ntb_transport_init_queue(struct ntb_transport_ctx *nt, > > qp->tx_max_entry = tx_size / qp->tx_max_frame; > > > > if (nt->debugfs_node_dir) { > > - char debugfs_name[4]; > > + char debugfs_name[8]; > > > > - snprintf(debugfs_name, 4, "qp%d", qp_num); > > + snprintf(debugfs_name, sizeof(debugfs_name), "qp%d", qp_num); > > qp->debugfs_dir = debugfs_create_dir(debugfs_name, > > nt->debugfs_node_dir); > > > > qp->debugfs_stats = debugfs_create_file("stats", S_IRUSR, > > qp->debugfs_dir, qp, > > - &ntb_qp_debugfs_stats); > > + &ntb_qp_debugfs_stats_fops); > > } else { > > qp->debugfs_dir = NULL; > > qp->debugfs_stats = NULL; >