[PATCH -next v5 30/32] ext4: add tracepoints for EOF block zeroing and disksize-grow I/O

Zhang Yi <[email protected]>
Newsgroups org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-ext4,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
From: Zhang Yi <[email protected]>

Add tracepoints to track the disksize-grow-pending lifecycle in the
writeback path and the block-zero-EOF entry point:

- ext4_iomap_wb_disksize_pending_submit: ioend is marked as
  DISKSIZE_GROW_IO in ext4_iomap_writeback_submit.
- ext4_iomap_wb_disksize_pending_complete: ioend of type
  DISKSIZE_GROW_IO completes in ext4_iomap_end_bio.
- ext4_iomap_wb_disksize_pending_wait: ioend worker waits for the
  pending zeroed EOF block to complete.
- ext4_iomap_wb_update_disksize: i_disksize is advanced in
  ext4_iomap_wb_update_disksize, including the new value and
  whether the update is a disksize-grow completion.
- ext4_block_zero_eof: ext4_block_zero_eof is called with the range
  and zeroing outcome, capturing the producer-side entry point.

Together with the previous mark/clear/wait tracepoints, these cover the
full lifetime of the disksize-grow-pending state.

Signed-off-by: Zhang Yi <[email protected]>
---
 fs/ext4/inode.c             |   3 +
 fs/ext4/page-io.c           |  13 ++++-
 include/trace/events/ext4.h | 107 ++++++++++++++++++++++++++++++++++++
 3 files changed, 121 insertions(+), 2 deletions(-)

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index bca7d5c33919..ee15366422a1 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -4406,6 +4406,8 @@ static int ext4_iomap_writeback_submit(struct iomap_writepage_ctx *wpc,
 	    round_down(ioend->io_offset, blocksize) <= pstart &&
 	    round_up(ioend->io_offset + ioend->io_size, blocksize) >=
 			pstart + plen) {
+		trace_ext4_iomap_wb_disksize_pending_submit(inode,
+				ioend->io_offset, ioend->io_size);
 		ioend->io_bio.bi_end_io = ext4_iomap_end_bio;
 		ioend->io_private = (void *)EXT4_IOMAP_IOEND_DISKSIZE_GROW_IO;
 	}
@@ -5001,6 +5003,7 @@ int ext4_block_zero_eof(struct inode *inode, loff_t from, loff_t end)
 			return err;
 	}
 
+	trace_ext4_block_zero_eof(inode, from, length, did_zero, zero_written);
 	return 0;
 }
 
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
index 4f1176b9332f..4464eb03c972 100644
--- a/fs/ext4/page-io.c
+++ b/fs/ext4/page-io.c
@@ -31,6 +31,8 @@
 #include "xattr.h"
 #include "acl.h"
 
+#include <trace/events/ext4.h>
+
 static struct kmem_cache *io_end_cachep;
 static struct kmem_cache *io_end_vec_cachep;
 
@@ -574,6 +576,7 @@ static void ext4_iomap_wb_disksize_pending_wait(struct inode *inode,
 	if (!plen || pos < pstart + plen)
 		return;
 
+	trace_ext4_iomap_wb_disksize_pending_wait(inode, pos, size);
 	ext4_iomap_wait_disksize_pending(inode);
 }
 
@@ -617,8 +620,11 @@ static int ext4_iomap_wb_update_disksize(handle_t *handle, struct inode *inode,
 	 * after the data has been persisted.
 	 */
 	new_disksize = is_disksize_grow ? i_size : min(end, i_size);
-	if (new_disksize > ei->i_disksize)
+	if (new_disksize > ei->i_disksize) {
+		trace_ext4_iomap_wb_update_disksize(inode, end, i_size,
+				ei->i_disksize, new_disksize, is_disksize_grow);
 		WRITE_ONCE(ei->i_disksize, new_disksize);
+	}
 	up_write(&ei->i_data_sem);
 	ret = ext4_mark_inode_dirty(handle, inode);
 	if (ret)
@@ -729,8 +735,11 @@ void ext4_iomap_end_bio(struct bio *bio)
 	 * state set in ext4_block_zero_eof() and wake up all waiters
 	 * that will update the inode i_disksize.
 	 */
-	if (io_mode == EXT4_IOMAP_IOEND_DISKSIZE_GROW_IO)
+	if (io_mode == EXT4_IOMAP_IOEND_DISKSIZE_GROW_IO) {
+		trace_ext4_iomap_wb_disksize_pending_complete(ioend->io_inode,
+				ioend->io_offset, ioend->io_size);
 		ext4_iomap_clear_disksize_pending(ioend->io_inode);
+	}
 
 	spin_lock_irqsave(&ei->i_completed_io_lock, flags);
 	if (list_empty(&ei->i_rsv_conversion_list))
diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
index 4539ef8e5f86..c9259c2a3e36 100644
--- a/include/trace/events/ext4.h
+++ b/include/trace/events/ext4.h
@@ -3237,6 +3237,113 @@ DEFINE_EVENT(ext4_iomap_disksize_pending, ext4_iomap_wait_disksize_pending,
 	TP_ARGS(inode)
 );
 
+/* disksize pending I/O tracepoints for iomap Buffered I/O path */
+DECLARE_EVENT_CLASS(ext4_iomap_wb_disksize_pending,
+	TP_PROTO(struct inode *inode, loff_t io_offset, size_t io_size),
+	TP_ARGS(inode, io_offset, io_size),
+	TP_STRUCT__entry(
+		__field(dev_t, dev)
+		__field(u64, ino)
+		__field(loff_t, io_offset)
+		__field(size_t, io_size)
+		__field(loff_t, i_size)
+		__field(loff_t, i_disksize)
+	),
+	TP_fast_assign(
+		__entry->dev = inode->i_sb->s_dev;
+		__entry->ino = inode->i_ino;
+		__entry->io_offset = io_offset;
+		__entry->io_size = io_size;
+		__entry->i_size = i_size_read(inode);
+		__entry->i_disksize = READ_ONCE(EXT4_I(inode)->i_disksize);
+	),
+	TP_printk("dev %d:%d ino %llu io_offset %lld io_size %zu i_size %lld i_disksize %lld",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  __entry->ino, __entry->io_offset, __entry->io_size,
+		  __entry->i_size, __entry->i_disksize)
+);
+
+DEFINE_EVENT(ext4_iomap_wb_disksize_pending,
+	ext4_iomap_wb_disksize_pending_submit,
+	TP_PROTO(struct inode *inode, loff_t io_offset, size_t io_size),
+	TP_ARGS(inode, io_offset, io_size)
+);
+
+DEFINE_EVENT(ext4_iomap_wb_disksize_pending,
+	ext4_iomap_wb_disksize_pending_complete,
+	TP_PROTO(struct inode *inode, loff_t io_offset, size_t io_size),
+	TP_ARGS(inode, io_offset, io_size)
+);
+
+DEFINE_EVENT(ext4_iomap_wb_disksize_pending,
+	ext4_iomap_wb_disksize_pending_wait,
+	TP_PROTO(struct inode *inode, loff_t io_offset, size_t io_size),
+	TP_ARGS(inode, io_offset, io_size)
+);
+
+/* i_disksize update tracepoint */
+TRACE_EVENT(ext4_iomap_wb_update_disksize,
+	TP_PROTO(struct inode *inode, loff_t end, loff_t i_size,
+		 loff_t i_disksize, loff_t new_disksize,
+		 bool is_disksize_grow),
+	TP_ARGS(inode, end, i_size, i_disksize, new_disksize,
+		is_disksize_grow),
+	TP_STRUCT__entry(
+		__field(dev_t, dev)
+		__field(u64, ino)
+		__field(loff_t, end)
+		__field(loff_t, i_size)
+		__field(loff_t, i_disksize)
+		__field(loff_t, new_disksize)
+		__field(bool, is_disksize_grow)
+	),
+	TP_fast_assign(
+		__entry->dev = inode->i_sb->s_dev;
+		__entry->ino = inode->i_ino;
+		__entry->end = end;
+		__entry->i_size = i_size;
+		__entry->i_disksize = i_disksize;
+		__entry->new_disksize = new_disksize;
+		__entry->is_disksize_grow = is_disksize_grow;
+	),
+	TP_printk("dev %d:%d ino %llu end %lld i_size %lld i_disksize %lld new_disksize %lld is_disksize_grow %d",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  __entry->ino, __entry->end, __entry->i_size,
+		  __entry->i_disksize, __entry->new_disksize,
+		  __entry->is_disksize_grow)
+);
+
+/* Block zero EOF tracepoint */
+TRACE_EVENT(ext4_block_zero_eof,
+	TP_PROTO(struct inode *inode, loff_t from, loff_t length,
+		 bool did_zero, bool zero_written),
+	TP_ARGS(inode, from, length, did_zero, zero_written),
+	TP_STRUCT__entry(
+		__field(dev_t, dev)
+		__field(u64, ino)
+		__field(loff_t, from)
+		__field(loff_t, length)
+		__field(loff_t, i_size)
+		__field(loff_t, i_disksize)
+		__field(bool, did_zero)
+		__field(bool, zero_written)
+	),
+	TP_fast_assign(
+		__entry->dev = inode->i_sb->s_dev;
+		__entry->ino = inode->i_ino;
+		__entry->from = from;
+		__entry->length = length;
+		__entry->i_size = inode->i_size;
+		__entry->i_disksize = READ_ONCE(EXT4_I(inode)->i_disksize);
+		__entry->did_zero = did_zero;
+		__entry->zero_written = zero_written;
+	),
+	TP_printk("dev %d:%d ino %llu zero EOF from %lld length %lld i_size %lld i_disksize %lld did_zero %d zero_written %d",
+		  MAJOR(__entry->dev), MINOR(__entry->dev), __entry->ino,
+		  __entry->from, __entry->length, __entry->i_size,
+		  __entry->i_disksize, __entry->did_zero, __entry->zero_written)
+);
+
 #endif /* _TRACE_EXT4_H */
 
 /* This part must be outside protection */
-- 
2.52.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.