Re: [PATCH] exfat: Add ftrace support for exfat and add some tracepoints

From: Google
Date: Mon Jul 10 2023 - 12:37:35 EST


On Mon, 10 Jul 2023 17:25:59 +0800
Zehao Zhang <zhangzehao@xxxxxxxx> wrote:

> Add ftrace support for exFAT file system,
> and add some tracepoints:
> exfat_read_folio(), exfat_writepages(), exfat_write_begin(),
> exfat_write_end(), exfat_lookup_start(), exfat_lookup_end()
>
> exfat_read_folio():
> shows the dev number, inode and the folio index.
>
> exfat_writepages():
> shows the inode and fields in struct writeback_control.
>
> exfat_write_begin():
> shows the inode, file position offset and length.
>
> exfat_write_end():
> shows the inode, file position offset, bytes write to page
> and bytes copied from user.
>
> exfat_lookup_start():
> shows the target inode, dentry and flags.
>
> exfat_lookup_end():
> shows the target inode, dentry and err code.

It seems like most of them are address_space_operations' operators.
Is that OK to define those events (~= user exposed interface) from
exFAT filesystem? I wonder why we can not make a generic VFS events
for those. (Or all FS-wide generic events).

Thank you,

>
> Signed-off-by: Zehao Zhang <zhangzehao@xxxxxxxx>
> ---
> MAINTAINERS | 1 +
> fs/exfat/inode.c | 16 +++
> fs/exfat/namei.c | 10 +-
> include/trace/events/exfat.h | 192 +++++++++++++++++++++++++++++++++++
> 4 files changed, 218 insertions(+), 1 deletion(-)
> create mode 100644 include/trace/events/exfat.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 4f115c355a41..fbe1caa61a38 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -7752,6 +7752,7 @@ L: linux-fsdevel@xxxxxxxxxxxxxxx
> S: Maintained
> T: git git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/exfat.git
> F: fs/exfat/
> +F: include/trace/events/exfat.h
>
> EXT2 FILE SYSTEM
> M: Jan Kara <jack@xxxxxxxx>
> diff --git a/fs/exfat/inode.c b/fs/exfat/inode.c
> index 481dd338f2b8..48fec3fa10af 100644
> --- a/fs/exfat/inode.c
> +++ b/fs/exfat/inode.c
> @@ -17,6 +17,9 @@
> #include "exfat_raw.h"
> #include "exfat_fs.h"
>
> +#define CREATE_TRACE_POINTS
> +#include <trace/events/exfat.h>
> +
> int __exfat_write_inode(struct inode *inode, int sync)
> {
> unsigned long long on_disk_size;
> @@ -335,6 +338,10 @@ static int exfat_get_block(struct inode *inode, sector_t iblock,
>
> static int exfat_read_folio(struct file *file, struct folio *folio)
> {
> + struct inode *inode = folio->mapping->host;
> +
> + trace_exfat_read_folio(inode, folio);
> +
> return mpage_read_folio(folio, exfat_get_block);
> }
>
> @@ -346,6 +353,10 @@ static void exfat_readahead(struct readahead_control *rac)
> static int exfat_writepages(struct address_space *mapping,
> struct writeback_control *wbc)
> {
> + struct inode *inode = mapping->host;
> +
> + trace_exfat_writepages(inode, wbc);
> +
> return mpage_writepages(mapping, wbc, exfat_get_block);
> }
>
> @@ -364,6 +375,7 @@ static int exfat_write_begin(struct file *file, struct address_space *mapping,
> loff_t pos, unsigned int len,
> struct page **pagep, void **fsdata)
> {
> + struct inode *inode = mapping->host;
> int ret;
>
> *pagep = NULL;
> @@ -371,6 +383,8 @@ static int exfat_write_begin(struct file *file, struct address_space *mapping,
> exfat_get_block,
> &EXFAT_I(mapping->host)->i_size_ondisk);
>
> + trace_exfat_write_begin(inode, pos, len);
> +
> if (ret < 0)
> exfat_write_failed(mapping, pos+len);
>
> @@ -394,6 +408,8 @@ static int exfat_write_end(struct file *file, struct address_space *mapping,
> return -EIO;
> }
>
> + trace_exfat_write_end(inode, pos, len, copied);
> +
> if (err < len)
> exfat_write_failed(mapping, pos+len);
>
> diff --git a/fs/exfat/namei.c b/fs/exfat/namei.c
> index e0ff9d156f6f..f4f36de4ca0d 100644
> --- a/fs/exfat/namei.c
> +++ b/fs/exfat/namei.c
> @@ -12,6 +12,8 @@
> #include "exfat_raw.h"
> #include "exfat_fs.h"
>
> +#include <trace/events/exfat.h>
> +
> static inline unsigned long exfat_d_version(struct dentry *dentry)
> {
> return (unsigned long) dentry->d_fsdata;
> @@ -707,6 +709,8 @@ static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry,
> loff_t i_pos;
> mode_t i_mode;
>
> + trace_exfat_lookup_start(dir, dentry, flags);
> +
> mutex_lock(&EXFAT_SB(sb)->s_lock);
> err = exfat_find(dir, &dentry->d_name, &info);
> if (err) {
> @@ -766,7 +770,11 @@ static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry,
> if (!inode)
> exfat_d_version_set(dentry, inode_query_iversion(dir));
>
> - return d_splice_alias(inode, dentry);
> + alias = d_splice_alias(inode, dentry);
> + trace_exfat_lookup_end(dir, !IS_ERR_OR_NULL(alias) ? alias : dentry,
> + IS_ERR(alias) ? PTR_ERR(alias) : err);
> +
> + return alias;
> unlock:
> mutex_unlock(&EXFAT_SB(sb)->s_lock);
> return ERR_PTR(err);
> diff --git a/include/trace/events/exfat.h b/include/trace/events/exfat.h
> new file mode 100644
> index 000000000000..67ac91c75cc6
> --- /dev/null
> +++ b/include/trace/events/exfat.h
> @@ -0,0 +1,192 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#undef TRACE_SYSTEM
> +#define TRACE_SYSTEM exfat
> +
> +#if !defined(_TRACE_EXFAT_H) || defined(TRACE_HEADER_MULTI_READ)
> +#define _TRACE_EXFAT_H
> +
> +#include <linux/tracepoint.h>
> +
> +#define EXFAT_I(inode) (container_of(inode, struct exfat_inode_info, vfs_inode))
> +
> +#define show_dev(dev) (MAJOR(dev), MINOR(dev))
> +#define show_dev_ino(entry) (show_dev(entry->dev), (unsigned long)entry->ino)
> +
> +
> +TRACE_EVENT(exfat_write_begin,
> + TP_PROTO(struct inode *inode, loff_t pos, unsigned int len),
> +
> + TP_ARGS(inode, pos, len),
> +
> + TP_STRUCT__entry(
> + __field(dev_t, dev)
> + __field(ino_t, ino)
> + __field(loff_t, pos)
> + __field(unsigned int, len)
> + ),
> +
> + TP_fast_assign(
> + __entry->dev = inode->i_sb->s_dev;
> + __entry->ino = inode->i_ino;
> + __entry->pos = pos;
> + __entry->len = len;
> + ),
> +
> + TP_printk("dev (%d,%d) ino %lu pos %lld len %u",
> + show_dev(__entry->dev),
> + (unsigned long) __entry->ino,
> + __entry->pos, __entry->len)
> +
> +);
> +
> +TRACE_EVENT(exfat_write_end,
> + TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
> + unsigned int copied),
> +
> + TP_ARGS(inode, pos, len, copied),
> +
> + TP_STRUCT__entry(
> + __field(dev_t, dev)
> + __field(ino_t, ino)
> + __field(loff_t, pos)
> + __field(unsigned int, len)
> + __field(unsigned int, copied)
> + ),
> +
> + TP_fast_assign(
> + __entry->dev = inode->i_sb->s_dev;
> + __entry->ino = inode->i_ino;
> + __entry->pos = pos;
> + __entry->len = len;
> + __entry->copied = copied;
> + ),
> +
> + TP_printk("dev (%d,%d) ino %lu pos %lld len %u copied %u",
> + show_dev(__entry->dev),
> + (unsigned long) __entry->ino,
> + __entry->pos, __entry->len, __entry->copied)
> +);
> +
> +TRACE_EVENT(exfat_read_folio,
> + TP_PROTO(struct inode *inode, struct folio *folio),
> +
> + TP_ARGS(inode, folio),
> +
> + TP_STRUCT__entry(
> + __field(dev_t, dev)
> + __field(ino_t, ino)
> + __field(pgoff_t, index)
> +
> + ),
> +
> + TP_fast_assign(
> + __entry->dev = inode->i_sb->s_dev;
> + __entry->ino = inode->i_ino;
> + __entry->index = folio->index;
> + ),
> +
> + TP_printk("dev (%d,%d) ino %lu folio_index %lu",
> + show_dev(__entry->dev),
> + (unsigned long) __entry->ino,
> + (unsigned long) __entry->index)
> +);
> +
> +TRACE_EVENT(exfat_writepages,
> + TP_PROTO(struct inode *inode, struct writeback_control *wbc),
> +
> + TP_ARGS(inode, wbc),
> +
> + TP_STRUCT__entry(
> + __field(dev_t, dev)
> + __field(ino_t, ino)
> + __field(long, nr_to_write)
> + __field(long, pages_skipped)
> + __field(loff_t, range_start)
> + __field(loff_t, range_end)
> + __field(pgoff_t, writeback_index)
> + __field(int, sync_mode)
> + __field(char, for_kupdate)
> + __field(char, range_cyclic)
> + ),
> +
> + TP_fast_assign(
> + __entry->dev = inode->i_sb->s_dev;
> + __entry->ino = inode->i_ino;
> + __entry->nr_to_write = wbc->nr_to_write;
> + __entry->pages_skipped = wbc->pages_skipped;
> + __entry->range_start = wbc->range_start;
> + __entry->range_end = wbc->range_end;
> + __entry->writeback_index = inode->i_mapping->writeback_index;
> + __entry->sync_mode = wbc->sync_mode;
> + __entry->for_kupdate = wbc->for_kupdate;
> + __entry->range_cyclic = wbc->range_cyclic;
> + ),
> +
> + TP_printk("dev (%d,%d) ino %lu nr_to_write %ld pages_skipped %ld "
> + "range_start %lld range_end %lld sync_mode %d "
> + "for_kupdate %d range_cyclic %d writeback_index %lu",
> + show_dev(__entry->dev),
> + (unsigned long) __entry->ino, __entry->nr_to_write,
> + __entry->pages_skipped, __entry->range_start,
> + __entry->range_end, __entry->sync_mode,
> + __entry->for_kupdate, __entry->range_cyclic,
> + (unsigned long) __entry->writeback_index)
> +);
> +
> +TRACE_EVENT(exfat_lookup_start,
> +
> + TP_PROTO(struct inode *dir, struct dentry *dentry, unsigned int flags),
> +
> + TP_ARGS(dir, dentry, flags),
> +
> + TP_STRUCT__entry(
> + __field(dev_t, dev)
> + __field(ino_t, ino)
> + __string(name, dentry->d_name.name)
> + __field(unsigned int, flags)
> + ),
> +
> + TP_fast_assign(
> + __entry->dev = dir->i_sb->s_dev;
> + __entry->ino = dir->i_ino;
> + __assign_str(name, dentry->d_name.name);
> + __entry->flags = flags;
> + ),
> +
> + TP_printk("dev = (%d,%d), pino = %lu, name:%s, flags:%u",
> + show_dev_ino(__entry),
> + __get_str(name),
> + __entry->flags)
> +);
> +
> +TRACE_EVENT(exfat_lookup_end,
> +
> + TP_PROTO(struct inode *dir, struct dentry *dentry,
> + int err),
> +
> + TP_ARGS(dir, dentry, err),
> +
> + TP_STRUCT__entry(
> + __field(dev_t, dev)
> + __field(ino_t, ino)
> + __string(name, dentry->d_name.name)
> + __field(int, err)
> + ),
> +
> + TP_fast_assign(
> + __entry->dev = dir->i_sb->s_dev;
> + __entry->ino = dir->i_ino;
> + __assign_str(name, dentry->d_name.name);
> + __entry->err = err;
> + ),
> +
> + TP_printk("dev = (%d,%d), pino = %lu, name:%s, err:%d",
> + show_dev_ino(__entry),
> + __get_str(name),
> + __entry->err)
> +);
> +
> +#endif /* _TRACE_EXFAT_H */
> +
> +/* This part must be outside protection */
> +#include <trace/define_trace.h>
> --
> 2.35.3
>


--
Masami Hiramatsu (Google) <mhiramat@xxxxxxxxxx>