Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9fb0a7da authored by Tejun Heo's avatar Tejun Heo Committed by Jens Axboe
Browse files

writeback: add more tracepoints



Add tracepoints for page dirtying, writeback_single_inode start, inode
dirtying and writeback.  For the latter two inode events, a pair of
events are defined to denote start and end of the operations (the
starting one has _start suffix and the one w/o suffix happens after
the operation is complete).  These inode ops are FS specific and can
be non-trivial and having enclosing tracepoints is useful for external
tracers.

This is part of tracepoint additions to improve visiblity into
dirtying / writeback operations for io tracer and userland.

v2: writeback_dirty_inode[_start] TPs may be called for files on
    pseudo FSes w/ unregistered bdi.  Check whether bdi->dev is %NULL
    before dereferencing.

v3: buffer dirtying moved to a block TP.

Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Reviewed-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 5305cb83
Loading
Loading
Loading
Loading
+14 −2
Original line number Original line Diff line number Diff line
@@ -318,8 +318,14 @@ static void queue_io(struct bdi_writeback *wb, struct wb_writeback_work *work)


static int write_inode(struct inode *inode, struct writeback_control *wbc)
static int write_inode(struct inode *inode, struct writeback_control *wbc)
{
{
	if (inode->i_sb->s_op->write_inode && !is_bad_inode(inode))
	int ret;
		return inode->i_sb->s_op->write_inode(inode, wbc);

	if (inode->i_sb->s_op->write_inode && !is_bad_inode(inode)) {
		trace_writeback_write_inode_start(inode, wbc);
		ret = inode->i_sb->s_op->write_inode(inode, wbc);
		trace_writeback_write_inode(inode, wbc);
		return ret;
	}
	return 0;
	return 0;
}
}


@@ -450,6 +456,8 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc)


	WARN_ON(!(inode->i_state & I_SYNC));
	WARN_ON(!(inode->i_state & I_SYNC));


	trace_writeback_single_inode_start(inode, wbc, nr_to_write);

	ret = do_writepages(mapping, wbc);
	ret = do_writepages(mapping, wbc);


	/*
	/*
@@ -1150,8 +1158,12 @@ void __mark_inode_dirty(struct inode *inode, int flags)
	 * dirty the inode itself
	 * dirty the inode itself
	 */
	 */
	if (flags & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) {
	if (flags & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) {
		trace_writeback_dirty_inode_start(inode, flags);

		if (sb->s_op->dirty_inode)
		if (sb->s_op->dirty_inode)
			sb->s_op->dirty_inode(inode, flags);
			sb->s_op->dirty_inode(inode, flags);

		trace_writeback_dirty_inode(inode, flags);
	}
	}


	/*
	/*
+116 −0
Original line number Original line Diff line number Diff line
@@ -32,6 +32,115 @@


struct wb_writeback_work;
struct wb_writeback_work;


TRACE_EVENT(writeback_dirty_page,

	TP_PROTO(struct page *page, struct address_space *mapping),

	TP_ARGS(page, mapping),

	TP_STRUCT__entry (
		__array(char, name, 32)
		__field(unsigned long, ino)
		__field(pgoff_t, index)
	),

	TP_fast_assign(
		strncpy(__entry->name,
			mapping ? dev_name(mapping->backing_dev_info->dev) : "(unknown)", 32);
		__entry->ino = mapping ? mapping->host->i_ino : 0;
		__entry->index = page->index;
	),

	TP_printk("bdi %s: ino=%lu index=%lu",
		__entry->name,
		__entry->ino,
		__entry->index
	)
);

DECLARE_EVENT_CLASS(writeback_dirty_inode_template,

	TP_PROTO(struct inode *inode, int flags),

	TP_ARGS(inode, flags),

	TP_STRUCT__entry (
		__array(char, name, 32)
		__field(unsigned long, ino)
		__field(unsigned long, flags)
	),

	TP_fast_assign(
		struct backing_dev_info *bdi = inode->i_mapping->backing_dev_info;

		/* may be called for files on pseudo FSes w/ unregistered bdi */
		strncpy(__entry->name,
			bdi->dev ? dev_name(bdi->dev) : "(unknown)", 32);
		__entry->ino		= inode->i_ino;
		__entry->flags		= flags;
	),

	TP_printk("bdi %s: ino=%lu flags=%s",
		__entry->name,
		__entry->ino,
		show_inode_state(__entry->flags)
	)
);

DEFINE_EVENT(writeback_dirty_inode_template, writeback_dirty_inode_start,

	TP_PROTO(struct inode *inode, int flags),

	TP_ARGS(inode, flags)
);

DEFINE_EVENT(writeback_dirty_inode_template, writeback_dirty_inode,

	TP_PROTO(struct inode *inode, int flags),

	TP_ARGS(inode, flags)
);

DECLARE_EVENT_CLASS(writeback_write_inode_template,

	TP_PROTO(struct inode *inode, struct writeback_control *wbc),

	TP_ARGS(inode, wbc),

	TP_STRUCT__entry (
		__array(char, name, 32)
		__field(unsigned long, ino)
		__field(int, sync_mode)
	),

	TP_fast_assign(
		strncpy(__entry->name,
			dev_name(inode->i_mapping->backing_dev_info->dev), 32);
		__entry->ino		= inode->i_ino;
		__entry->sync_mode	= wbc->sync_mode;
	),

	TP_printk("bdi %s: ino=%lu sync_mode=%d",
		__entry->name,
		__entry->ino,
		__entry->sync_mode
	)
);

DEFINE_EVENT(writeback_write_inode_template, writeback_write_inode_start,

	TP_PROTO(struct inode *inode, struct writeback_control *wbc),

	TP_ARGS(inode, wbc)
);

DEFINE_EVENT(writeback_write_inode_template, writeback_write_inode,

	TP_PROTO(struct inode *inode, struct writeback_control *wbc),

	TP_ARGS(inode, wbc)
);

DECLARE_EVENT_CLASS(writeback_work_class,
DECLARE_EVENT_CLASS(writeback_work_class,
	TP_PROTO(struct backing_dev_info *bdi, struct wb_writeback_work *work),
	TP_PROTO(struct backing_dev_info *bdi, struct wb_writeback_work *work),
	TP_ARGS(bdi, work),
	TP_ARGS(bdi, work),
@@ -479,6 +588,13 @@ DECLARE_EVENT_CLASS(writeback_single_inode_template,
	)
	)
);
);


DEFINE_EVENT(writeback_single_inode_template, writeback_single_inode_start,
	TP_PROTO(struct inode *inode,
		 struct writeback_control *wbc,
		 unsigned long nr_to_write),
	TP_ARGS(inode, wbc, nr_to_write)
);

DEFINE_EVENT(writeback_single_inode_template, writeback_single_inode,
DEFINE_EVENT(writeback_single_inode_template, writeback_single_inode,
	TP_PROTO(struct inode *inode,
	TP_PROTO(struct inode *inode,
		 struct writeback_control *wbc,
		 struct writeback_control *wbc,
+2 −0
Original line number Original line Diff line number Diff line
@@ -1982,6 +1982,8 @@ int __set_page_dirty_no_writeback(struct page *page)
 */
 */
void account_page_dirtied(struct page *page, struct address_space *mapping)
void account_page_dirtied(struct page *page, struct address_space *mapping)
{
{
	trace_writeback_dirty_page(page, mapping);

	if (mapping_cap_account_dirty(mapping)) {
	if (mapping_cap_account_dirty(mapping)) {
		__inc_zone_page_state(page, NR_FILE_DIRTY);
		__inc_zone_page_state(page, NR_FILE_DIRTY);
		__inc_zone_page_state(page, NR_DIRTIED);
		__inc_zone_page_state(page, NR_DIRTIED);