xfs: optimize writes to reflink files
[cascardo/linux.git] / fs / xfs / xfs_trace.h
index 16093c7..72f9f6b 100644 (file)
@@ -39,6 +39,7 @@ struct xfs_buf_log_format;
 struct xfs_inode_log_format;
 struct xfs_bmbt_irec;
 struct xfs_btree_cur;
+struct xfs_refcount_irec;
 
 DECLARE_EVENT_CLASS(xfs_attr_list_class,
        TP_PROTO(struct xfs_attr_list_context *ctx),
@@ -135,6 +136,8 @@ DEFINE_PERAG_REF_EVENT(xfs_perag_set_reclaim);
 DEFINE_PERAG_REF_EVENT(xfs_perag_clear_reclaim);
 DEFINE_PERAG_REF_EVENT(xfs_perag_set_eofblocks);
 DEFINE_PERAG_REF_EVENT(xfs_perag_clear_eofblocks);
+DEFINE_PERAG_REF_EVENT(xfs_perag_set_cowblocks);
+DEFINE_PERAG_REF_EVENT(xfs_perag_clear_cowblocks);
 
 DECLARE_EVENT_CLASS(xfs_ag_class,
        TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno),
@@ -268,10 +271,10 @@ DECLARE_EVENT_CLASS(xfs_bmap_class,
                __field(unsigned long, caller_ip)
        ),
        TP_fast_assign(
-               struct xfs_ifork        *ifp = (state & BMAP_ATTRFORK) ?
-                                               ip->i_afp : &ip->i_df;
+               struct xfs_ifork        *ifp;
                struct xfs_bmbt_irec    r;
 
+               ifp = xfs_iext_state_to_fork(ip, state);
                xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx), &r);
                __entry->dev = VFS_I(ip)->i_sb->s_dev;
                __entry->ino = ip->i_ino;
@@ -686,6 +689,9 @@ DEFINE_INODE_EVENT(xfs_dquot_dqdetach);
 DEFINE_INODE_EVENT(xfs_inode_set_eofblocks_tag);
 DEFINE_INODE_EVENT(xfs_inode_clear_eofblocks_tag);
 DEFINE_INODE_EVENT(xfs_inode_free_eofblocks_invalid);
+DEFINE_INODE_EVENT(xfs_inode_set_cowblocks_tag);
+DEFINE_INODE_EVENT(xfs_inode_clear_cowblocks_tag);
+DEFINE_INODE_EVENT(xfs_inode_free_cowblocks_invalid);
 
 DEFINE_INODE_EVENT(xfs_filemap_fault);
 DEFINE_INODE_EVENT(xfs_filemap_pmd_fault);
@@ -2581,10 +2587,20 @@ DEFINE_RMAPBT_EVENT(xfs_rmap_delete);
 DEFINE_AG_ERROR_EVENT(xfs_rmap_insert_error);
 DEFINE_AG_ERROR_EVENT(xfs_rmap_delete_error);
 DEFINE_AG_ERROR_EVENT(xfs_rmap_update_error);
+
+DEFINE_RMAPBT_EVENT(xfs_rmap_find_left_neighbor_candidate);
+DEFINE_RMAPBT_EVENT(xfs_rmap_find_left_neighbor_query);
+DEFINE_RMAPBT_EVENT(xfs_rmap_lookup_le_range_candidate);
+DEFINE_RMAPBT_EVENT(xfs_rmap_lookup_le_range);
 DEFINE_RMAPBT_EVENT(xfs_rmap_lookup_le_range_result);
 DEFINE_RMAPBT_EVENT(xfs_rmap_find_right_neighbor_result);
 DEFINE_RMAPBT_EVENT(xfs_rmap_find_left_neighbor_result);
 
+/* deferred bmbt updates */
+#define DEFINE_BMAP_DEFERRED_EVENT     DEFINE_RMAP_DEFERRED_EVENT
+DEFINE_BMAP_DEFERRED_EVENT(xfs_bmap_defer);
+DEFINE_BMAP_DEFERRED_EVENT(xfs_bmap_deferred);
+
 /* per-AG reservation */
 DECLARE_EVENT_CLASS(xfs_ag_resv_class,
        TP_PROTO(struct xfs_perag *pag, enum xfs_ag_resv_type resv,
@@ -2639,6 +2655,727 @@ DEFINE_AG_RESV_EVENT(xfs_ag_resv_needed);
 DEFINE_AG_ERROR_EVENT(xfs_ag_resv_free_error);
 DEFINE_AG_ERROR_EVENT(xfs_ag_resv_init_error);
 
+/* refcount tracepoint classes */
+
+/* reuse the discard trace class for agbno/aglen-based traces */
+#define DEFINE_AG_EXTENT_EVENT(name) DEFINE_DISCARD_EVENT(name)
+
+/* ag btree lookup tracepoint class */
+#define XFS_AG_BTREE_CMP_FORMAT_STR \
+       { XFS_LOOKUP_EQ,        "eq" }, \
+       { XFS_LOOKUP_LE,        "le" }, \
+       { XFS_LOOKUP_GE,        "ge" }
+DECLARE_EVENT_CLASS(xfs_ag_btree_lookup_class,
+       TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno,
+                xfs_agblock_t agbno, xfs_lookup_t dir),
+       TP_ARGS(mp, agno, agbno, dir),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_agnumber_t, agno)
+               __field(xfs_agblock_t, agbno)
+               __field(xfs_lookup_t, dir)
+       ),
+       TP_fast_assign(
+               __entry->dev = mp->m_super->s_dev;
+               __entry->agno = agno;
+               __entry->agbno = agbno;
+               __entry->dir = dir;
+       ),
+       TP_printk("dev %d:%d agno %u agbno %u cmp %s(%d)\n",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->agno,
+                 __entry->agbno,
+                 __print_symbolic(__entry->dir, XFS_AG_BTREE_CMP_FORMAT_STR),
+                 __entry->dir)
+)
+
+#define DEFINE_AG_BTREE_LOOKUP_EVENT(name) \
+DEFINE_EVENT(xfs_ag_btree_lookup_class, name, \
+       TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \
+                xfs_agblock_t agbno, xfs_lookup_t dir), \
+       TP_ARGS(mp, agno, agbno, dir))
+
+/* single-rcext tracepoint class */
+DECLARE_EVENT_CLASS(xfs_refcount_extent_class,
+       TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno,
+                struct xfs_refcount_irec *irec),
+       TP_ARGS(mp, agno, irec),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_agnumber_t, agno)
+               __field(xfs_agblock_t, startblock)
+               __field(xfs_extlen_t, blockcount)
+               __field(xfs_nlink_t, refcount)
+       ),
+       TP_fast_assign(
+               __entry->dev = mp->m_super->s_dev;
+               __entry->agno = agno;
+               __entry->startblock = irec->rc_startblock;
+               __entry->blockcount = irec->rc_blockcount;
+               __entry->refcount = irec->rc_refcount;
+       ),
+       TP_printk("dev %d:%d agno %u agbno %u len %u refcount %u\n",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->agno,
+                 __entry->startblock,
+                 __entry->blockcount,
+                 __entry->refcount)
+)
+
+#define DEFINE_REFCOUNT_EXTENT_EVENT(name) \
+DEFINE_EVENT(xfs_refcount_extent_class, name, \
+       TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \
+                struct xfs_refcount_irec *irec), \
+       TP_ARGS(mp, agno, irec))
+
+/* single-rcext and an agbno tracepoint class */
+DECLARE_EVENT_CLASS(xfs_refcount_extent_at_class,
+       TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno,
+                struct xfs_refcount_irec *irec, xfs_agblock_t agbno),
+       TP_ARGS(mp, agno, irec, agbno),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_agnumber_t, agno)
+               __field(xfs_agblock_t, startblock)
+               __field(xfs_extlen_t, blockcount)
+               __field(xfs_nlink_t, refcount)
+               __field(xfs_agblock_t, agbno)
+       ),
+       TP_fast_assign(
+               __entry->dev = mp->m_super->s_dev;
+               __entry->agno = agno;
+               __entry->startblock = irec->rc_startblock;
+               __entry->blockcount = irec->rc_blockcount;
+               __entry->refcount = irec->rc_refcount;
+               __entry->agbno = agbno;
+       ),
+       TP_printk("dev %d:%d agno %u agbno %u len %u refcount %u @ agbno %u\n",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->agno,
+                 __entry->startblock,
+                 __entry->blockcount,
+                 __entry->refcount,
+                 __entry->agbno)
+)
+
+#define DEFINE_REFCOUNT_EXTENT_AT_EVENT(name) \
+DEFINE_EVENT(xfs_refcount_extent_at_class, name, \
+       TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \
+                struct xfs_refcount_irec *irec, xfs_agblock_t agbno), \
+       TP_ARGS(mp, agno, irec, agbno))
+
+/* double-rcext tracepoint class */
+DECLARE_EVENT_CLASS(xfs_refcount_double_extent_class,
+       TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno,
+                struct xfs_refcount_irec *i1, struct xfs_refcount_irec *i2),
+       TP_ARGS(mp, agno, i1, i2),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_agnumber_t, agno)
+               __field(xfs_agblock_t, i1_startblock)
+               __field(xfs_extlen_t, i1_blockcount)
+               __field(xfs_nlink_t, i1_refcount)
+               __field(xfs_agblock_t, i2_startblock)
+               __field(xfs_extlen_t, i2_blockcount)
+               __field(xfs_nlink_t, i2_refcount)
+       ),
+       TP_fast_assign(
+               __entry->dev = mp->m_super->s_dev;
+               __entry->agno = agno;
+               __entry->i1_startblock = i1->rc_startblock;
+               __entry->i1_blockcount = i1->rc_blockcount;
+               __entry->i1_refcount = i1->rc_refcount;
+               __entry->i2_startblock = i2->rc_startblock;
+               __entry->i2_blockcount = i2->rc_blockcount;
+               __entry->i2_refcount = i2->rc_refcount;
+       ),
+       TP_printk("dev %d:%d agno %u agbno %u len %u refcount %u -- "
+                 "agbno %u len %u refcount %u\n",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->agno,
+                 __entry->i1_startblock,
+                 __entry->i1_blockcount,
+                 __entry->i1_refcount,
+                 __entry->i2_startblock,
+                 __entry->i2_blockcount,
+                 __entry->i2_refcount)
+)
+
+#define DEFINE_REFCOUNT_DOUBLE_EXTENT_EVENT(name) \
+DEFINE_EVENT(xfs_refcount_double_extent_class, name, \
+       TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \
+                struct xfs_refcount_irec *i1, struct xfs_refcount_irec *i2), \
+       TP_ARGS(mp, agno, i1, i2))
+
+/* double-rcext and an agbno tracepoint class */
+DECLARE_EVENT_CLASS(xfs_refcount_double_extent_at_class,
+       TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno,
+                struct xfs_refcount_irec *i1, struct xfs_refcount_irec *i2,
+                xfs_agblock_t agbno),
+       TP_ARGS(mp, agno, i1, i2, agbno),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_agnumber_t, agno)
+               __field(xfs_agblock_t, i1_startblock)
+               __field(xfs_extlen_t, i1_blockcount)
+               __field(xfs_nlink_t, i1_refcount)
+               __field(xfs_agblock_t, i2_startblock)
+               __field(xfs_extlen_t, i2_blockcount)
+               __field(xfs_nlink_t, i2_refcount)
+               __field(xfs_agblock_t, agbno)
+       ),
+       TP_fast_assign(
+               __entry->dev = mp->m_super->s_dev;
+               __entry->agno = agno;
+               __entry->i1_startblock = i1->rc_startblock;
+               __entry->i1_blockcount = i1->rc_blockcount;
+               __entry->i1_refcount = i1->rc_refcount;
+               __entry->i2_startblock = i2->rc_startblock;
+               __entry->i2_blockcount = i2->rc_blockcount;
+               __entry->i2_refcount = i2->rc_refcount;
+               __entry->agbno = agbno;
+       ),
+       TP_printk("dev %d:%d agno %u agbno %u len %u refcount %u -- "
+                 "agbno %u len %u refcount %u @ agbno %u\n",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->agno,
+                 __entry->i1_startblock,
+                 __entry->i1_blockcount,
+                 __entry->i1_refcount,
+                 __entry->i2_startblock,
+                 __entry->i2_blockcount,
+                 __entry->i2_refcount,
+                 __entry->agbno)
+)
+
+#define DEFINE_REFCOUNT_DOUBLE_EXTENT_AT_EVENT(name) \
+DEFINE_EVENT(xfs_refcount_double_extent_at_class, name, \
+       TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \
+                struct xfs_refcount_irec *i1, struct xfs_refcount_irec *i2, \
+                xfs_agblock_t agbno), \
+       TP_ARGS(mp, agno, i1, i2, agbno))
+
+/* triple-rcext tracepoint class */
+DECLARE_EVENT_CLASS(xfs_refcount_triple_extent_class,
+       TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno,
+                struct xfs_refcount_irec *i1, struct xfs_refcount_irec *i2,
+                struct xfs_refcount_irec *i3),
+       TP_ARGS(mp, agno, i1, i2, i3),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_agnumber_t, agno)
+               __field(xfs_agblock_t, i1_startblock)
+               __field(xfs_extlen_t, i1_blockcount)
+               __field(xfs_nlink_t, i1_refcount)
+               __field(xfs_agblock_t, i2_startblock)
+               __field(xfs_extlen_t, i2_blockcount)
+               __field(xfs_nlink_t, i2_refcount)
+               __field(xfs_agblock_t, i3_startblock)
+               __field(xfs_extlen_t, i3_blockcount)
+               __field(xfs_nlink_t, i3_refcount)
+       ),
+       TP_fast_assign(
+               __entry->dev = mp->m_super->s_dev;
+               __entry->agno = agno;
+               __entry->i1_startblock = i1->rc_startblock;
+               __entry->i1_blockcount = i1->rc_blockcount;
+               __entry->i1_refcount = i1->rc_refcount;
+               __entry->i2_startblock = i2->rc_startblock;
+               __entry->i2_blockcount = i2->rc_blockcount;
+               __entry->i2_refcount = i2->rc_refcount;
+               __entry->i3_startblock = i3->rc_startblock;
+               __entry->i3_blockcount = i3->rc_blockcount;
+               __entry->i3_refcount = i3->rc_refcount;
+       ),
+       TP_printk("dev %d:%d agno %u agbno %u len %u refcount %u -- "
+                 "agbno %u len %u refcount %u -- "
+                 "agbno %u len %u refcount %u\n",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->agno,
+                 __entry->i1_startblock,
+                 __entry->i1_blockcount,
+                 __entry->i1_refcount,
+                 __entry->i2_startblock,
+                 __entry->i2_blockcount,
+                 __entry->i2_refcount,
+                 __entry->i3_startblock,
+                 __entry->i3_blockcount,
+                 __entry->i3_refcount)
+);
+
+#define DEFINE_REFCOUNT_TRIPLE_EXTENT_EVENT(name) \
+DEFINE_EVENT(xfs_refcount_triple_extent_class, name, \
+       TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \
+                struct xfs_refcount_irec *i1, struct xfs_refcount_irec *i2, \
+                struct xfs_refcount_irec *i3), \
+       TP_ARGS(mp, agno, i1, i2, i3))
+
+/* refcount btree tracepoints */
+DEFINE_BUSY_EVENT(xfs_refcountbt_alloc_block);
+DEFINE_BUSY_EVENT(xfs_refcountbt_free_block);
+DEFINE_AG_BTREE_LOOKUP_EVENT(xfs_refcount_lookup);
+DEFINE_REFCOUNT_EXTENT_EVENT(xfs_refcount_get);
+DEFINE_REFCOUNT_EXTENT_EVENT(xfs_refcount_update);
+DEFINE_REFCOUNT_EXTENT_EVENT(xfs_refcount_insert);
+DEFINE_REFCOUNT_EXTENT_EVENT(xfs_refcount_delete);
+DEFINE_AG_ERROR_EVENT(xfs_refcount_insert_error);
+DEFINE_AG_ERROR_EVENT(xfs_refcount_delete_error);
+DEFINE_AG_ERROR_EVENT(xfs_refcount_update_error);
+
+/* refcount adjustment tracepoints */
+DEFINE_AG_EXTENT_EVENT(xfs_refcount_increase);
+DEFINE_AG_EXTENT_EVENT(xfs_refcount_decrease);
+DEFINE_AG_EXTENT_EVENT(xfs_refcount_cow_increase);
+DEFINE_AG_EXTENT_EVENT(xfs_refcount_cow_decrease);
+DEFINE_REFCOUNT_TRIPLE_EXTENT_EVENT(xfs_refcount_merge_center_extents);
+DEFINE_REFCOUNT_EXTENT_EVENT(xfs_refcount_modify_extent);
+DEFINE_REFCOUNT_EXTENT_EVENT(xfs_refcount_recover_extent);
+DEFINE_REFCOUNT_EXTENT_AT_EVENT(xfs_refcount_split_extent);
+DEFINE_REFCOUNT_DOUBLE_EXTENT_EVENT(xfs_refcount_merge_left_extent);
+DEFINE_REFCOUNT_DOUBLE_EXTENT_EVENT(xfs_refcount_merge_right_extent);
+DEFINE_REFCOUNT_DOUBLE_EXTENT_AT_EVENT(xfs_refcount_find_left_extent);
+DEFINE_REFCOUNT_DOUBLE_EXTENT_AT_EVENT(xfs_refcount_find_right_extent);
+DEFINE_AG_ERROR_EVENT(xfs_refcount_adjust_error);
+DEFINE_AG_ERROR_EVENT(xfs_refcount_adjust_cow_error);
+DEFINE_AG_ERROR_EVENT(xfs_refcount_merge_center_extents_error);
+DEFINE_AG_ERROR_EVENT(xfs_refcount_modify_extent_error);
+DEFINE_AG_ERROR_EVENT(xfs_refcount_split_extent_error);
+DEFINE_AG_ERROR_EVENT(xfs_refcount_merge_left_extent_error);
+DEFINE_AG_ERROR_EVENT(xfs_refcount_merge_right_extent_error);
+DEFINE_AG_ERROR_EVENT(xfs_refcount_find_left_extent_error);
+DEFINE_AG_ERROR_EVENT(xfs_refcount_find_right_extent_error);
+
+/* reflink helpers */
+DEFINE_AG_EXTENT_EVENT(xfs_refcount_find_shared);
+DEFINE_AG_EXTENT_EVENT(xfs_refcount_find_shared_result);
+DEFINE_AG_ERROR_EVENT(xfs_refcount_find_shared_error);
+#define DEFINE_REFCOUNT_DEFERRED_EVENT DEFINE_PHYS_EXTENT_DEFERRED_EVENT
+DEFINE_REFCOUNT_DEFERRED_EVENT(xfs_refcount_defer);
+DEFINE_REFCOUNT_DEFERRED_EVENT(xfs_refcount_deferred);
+
+TRACE_EVENT(xfs_refcount_finish_one_leftover,
+       TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno,
+                int type, xfs_agblock_t agbno, xfs_extlen_t len,
+                xfs_agblock_t new_agbno, xfs_extlen_t new_len),
+       TP_ARGS(mp, agno, type, agbno, len, new_agbno, new_len),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_agnumber_t, agno)
+               __field(int, type)
+               __field(xfs_agblock_t, agbno)
+               __field(xfs_extlen_t, len)
+               __field(xfs_agblock_t, new_agbno)
+               __field(xfs_extlen_t, new_len)
+       ),
+       TP_fast_assign(
+               __entry->dev = mp->m_super->s_dev;
+               __entry->agno = agno;
+               __entry->type = type;
+               __entry->agbno = agbno;
+               __entry->len = len;
+               __entry->new_agbno = new_agbno;
+               __entry->new_len = new_len;
+       ),
+       TP_printk("dev %d:%d type %d agno %u agbno %u len %u new_agbno %u new_len %u",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->type,
+                 __entry->agno,
+                 __entry->agbno,
+                 __entry->len,
+                 __entry->new_agbno,
+                 __entry->new_len)
+);
+
+/* simple inode-based error/%ip tracepoint class */
+DECLARE_EVENT_CLASS(xfs_inode_error_class,
+       TP_PROTO(struct xfs_inode *ip, int error, unsigned long caller_ip),
+       TP_ARGS(ip, error, caller_ip),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_ino_t, ino)
+               __field(int, error)
+               __field(unsigned long, caller_ip)
+       ),
+       TP_fast_assign(
+               __entry->dev = VFS_I(ip)->i_sb->s_dev;
+               __entry->ino = ip->i_ino;
+               __entry->error = error;
+               __entry->caller_ip = caller_ip;
+       ),
+       TP_printk("dev %d:%d ino %llx error %d caller %ps",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->ino,
+                 __entry->error,
+                 (char *)__entry->caller_ip)
+);
+
+#define DEFINE_INODE_ERROR_EVENT(name) \
+DEFINE_EVENT(xfs_inode_error_class, name, \
+       TP_PROTO(struct xfs_inode *ip, int error, \
+                unsigned long caller_ip), \
+       TP_ARGS(ip, error, caller_ip))
+
+/* reflink allocator */
+TRACE_EVENT(xfs_bmap_remap_alloc,
+       TP_PROTO(struct xfs_inode *ip, xfs_fsblock_t fsbno,
+                xfs_extlen_t len),
+       TP_ARGS(ip, fsbno, len),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_ino_t, ino)
+               __field(xfs_fsblock_t, fsbno)
+               __field(xfs_extlen_t, len)
+       ),
+       TP_fast_assign(
+               __entry->dev = VFS_I(ip)->i_sb->s_dev;
+               __entry->ino = ip->i_ino;
+               __entry->fsbno = fsbno;
+               __entry->len = len;
+       ),
+       TP_printk("dev %d:%d ino 0x%llx fsbno 0x%llx len %x",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->ino,
+                 __entry->fsbno,
+                 __entry->len)
+);
+DEFINE_INODE_ERROR_EVENT(xfs_bmap_remap_alloc_error);
+
+/* reflink tracepoint classes */
+
+/* two-file io tracepoint class */
+DECLARE_EVENT_CLASS(xfs_double_io_class,
+       TP_PROTO(struct xfs_inode *src, xfs_off_t soffset, xfs_off_t len,
+                struct xfs_inode *dest, xfs_off_t doffset),
+       TP_ARGS(src, soffset, len, dest, doffset),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_ino_t, src_ino)
+               __field(loff_t, src_isize)
+               __field(loff_t, src_disize)
+               __field(loff_t, src_offset)
+               __field(size_t, len)
+               __field(xfs_ino_t, dest_ino)
+               __field(loff_t, dest_isize)
+               __field(loff_t, dest_disize)
+               __field(loff_t, dest_offset)
+       ),
+       TP_fast_assign(
+               __entry->dev = VFS_I(src)->i_sb->s_dev;
+               __entry->src_ino = src->i_ino;
+               __entry->src_isize = VFS_I(src)->i_size;
+               __entry->src_disize = src->i_d.di_size;
+               __entry->src_offset = soffset;
+               __entry->len = len;
+               __entry->dest_ino = dest->i_ino;
+               __entry->dest_isize = VFS_I(dest)->i_size;
+               __entry->dest_disize = dest->i_d.di_size;
+               __entry->dest_offset = doffset;
+       ),
+       TP_printk("dev %d:%d count %zd "
+                 "ino 0x%llx isize 0x%llx disize 0x%llx offset 0x%llx -> "
+                 "ino 0x%llx isize 0x%llx disize 0x%llx offset 0x%llx",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->len,
+                 __entry->src_ino,
+                 __entry->src_isize,
+                 __entry->src_disize,
+                 __entry->src_offset,
+                 __entry->dest_ino,
+                 __entry->dest_isize,
+                 __entry->dest_disize,
+                 __entry->dest_offset)
+)
+
+#define DEFINE_DOUBLE_IO_EVENT(name)   \
+DEFINE_EVENT(xfs_double_io_class, name,        \
+       TP_PROTO(struct xfs_inode *src, xfs_off_t soffset, xfs_off_t len, \
+                struct xfs_inode *dest, xfs_off_t doffset), \
+       TP_ARGS(src, soffset, len, dest, doffset))
+
+/* two-file vfs io tracepoint class */
+DECLARE_EVENT_CLASS(xfs_double_vfs_io_class,
+       TP_PROTO(struct inode *src, u64 soffset, u64 len,
+                struct inode *dest, u64 doffset),
+       TP_ARGS(src, soffset, len, dest, doffset),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(unsigned long, src_ino)
+               __field(loff_t, src_isize)
+               __field(loff_t, src_offset)
+               __field(size_t, len)
+               __field(unsigned long, dest_ino)
+               __field(loff_t, dest_isize)
+               __field(loff_t, dest_offset)
+       ),
+       TP_fast_assign(
+               __entry->dev = src->i_sb->s_dev;
+               __entry->src_ino = src->i_ino;
+               __entry->src_isize = i_size_read(src);
+               __entry->src_offset = soffset;
+               __entry->len = len;
+               __entry->dest_ino = dest->i_ino;
+               __entry->dest_isize = i_size_read(dest);
+               __entry->dest_offset = doffset;
+       ),
+       TP_printk("dev %d:%d count %zd "
+                 "ino 0x%lx isize 0x%llx offset 0x%llx -> "
+                 "ino 0x%lx isize 0x%llx offset 0x%llx",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->len,
+                 __entry->src_ino,
+                 __entry->src_isize,
+                 __entry->src_offset,
+                 __entry->dest_ino,
+                 __entry->dest_isize,
+                 __entry->dest_offset)
+)
+
+#define DEFINE_DOUBLE_VFS_IO_EVENT(name)       \
+DEFINE_EVENT(xfs_double_vfs_io_class, name,    \
+       TP_PROTO(struct inode *src, u64 soffset, u64 len, \
+                struct inode *dest, u64 doffset), \
+       TP_ARGS(src, soffset, len, dest, doffset))
+
+/* CoW write tracepoint */
+DECLARE_EVENT_CLASS(xfs_copy_on_write_class,
+       TP_PROTO(struct xfs_inode *ip, xfs_fileoff_t lblk, xfs_fsblock_t pblk,
+                xfs_extlen_t len, xfs_fsblock_t new_pblk),
+       TP_ARGS(ip, lblk, pblk, len, new_pblk),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_ino_t, ino)
+               __field(xfs_fileoff_t, lblk)
+               __field(xfs_fsblock_t, pblk)
+               __field(xfs_extlen_t, len)
+               __field(xfs_fsblock_t, new_pblk)
+       ),
+       TP_fast_assign(
+               __entry->dev = VFS_I(ip)->i_sb->s_dev;
+               __entry->ino = ip->i_ino;
+               __entry->lblk = lblk;
+               __entry->pblk = pblk;
+               __entry->len = len;
+               __entry->new_pblk = new_pblk;
+       ),
+       TP_printk("dev %d:%d ino 0x%llx lblk 0x%llx pblk 0x%llx "
+                 "len 0x%x new_pblk %llu",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->ino,
+                 __entry->lblk,
+                 __entry->pblk,
+                 __entry->len,
+                 __entry->new_pblk)
+)
+
+#define DEFINE_COW_EVENT(name) \
+DEFINE_EVENT(xfs_copy_on_write_class, name,    \
+       TP_PROTO(struct xfs_inode *ip, xfs_fileoff_t lblk, xfs_fsblock_t pblk, \
+                xfs_extlen_t len, xfs_fsblock_t new_pblk), \
+       TP_ARGS(ip, lblk, pblk, len, new_pblk))
+
+/* inode/irec events */
+DECLARE_EVENT_CLASS(xfs_inode_irec_class,
+       TP_PROTO(struct xfs_inode *ip, struct xfs_bmbt_irec *irec),
+       TP_ARGS(ip, irec),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_ino_t, ino)
+               __field(xfs_fileoff_t, lblk)
+               __field(xfs_extlen_t, len)
+               __field(xfs_fsblock_t, pblk)
+       ),
+       TP_fast_assign(
+               __entry->dev = VFS_I(ip)->i_sb->s_dev;
+               __entry->ino = ip->i_ino;
+               __entry->lblk = irec->br_startoff;
+               __entry->len = irec->br_blockcount;
+               __entry->pblk = irec->br_startblock;
+       ),
+       TP_printk("dev %d:%d ino 0x%llx lblk 0x%llx len 0x%x pblk %llu",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->ino,
+                 __entry->lblk,
+                 __entry->len,
+                 __entry->pblk)
+);
+#define DEFINE_INODE_IREC_EVENT(name) \
+DEFINE_EVENT(xfs_inode_irec_class, name, \
+       TP_PROTO(struct xfs_inode *ip, struct xfs_bmbt_irec *irec), \
+       TP_ARGS(ip, irec))
+
+/* refcount/reflink tracepoint definitions */
+
+/* reflink tracepoints */
+DEFINE_INODE_EVENT(xfs_reflink_set_inode_flag);
+DEFINE_INODE_EVENT(xfs_reflink_unset_inode_flag);
+DEFINE_ITRUNC_EVENT(xfs_reflink_update_inode_size);
+DEFINE_IOMAP_EVENT(xfs_reflink_remap_imap);
+TRACE_EVENT(xfs_reflink_remap_blocks_loop,
+       TP_PROTO(struct xfs_inode *src, xfs_fileoff_t soffset,
+                xfs_filblks_t len, struct xfs_inode *dest,
+                xfs_fileoff_t doffset),
+       TP_ARGS(src, soffset, len, dest, doffset),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_ino_t, src_ino)
+               __field(xfs_fileoff_t, src_lblk)
+               __field(xfs_filblks_t, len)
+               __field(xfs_ino_t, dest_ino)
+               __field(xfs_fileoff_t, dest_lblk)
+       ),
+       TP_fast_assign(
+               __entry->dev = VFS_I(src)->i_sb->s_dev;
+               __entry->src_ino = src->i_ino;
+               __entry->src_lblk = soffset;
+               __entry->len = len;
+               __entry->dest_ino = dest->i_ino;
+               __entry->dest_lblk = doffset;
+       ),
+       TP_printk("dev %d:%d len 0x%llx "
+                 "ino 0x%llx offset 0x%llx blocks -> "
+                 "ino 0x%llx offset 0x%llx blocks",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->len,
+                 __entry->src_ino,
+                 __entry->src_lblk,
+                 __entry->dest_ino,
+                 __entry->dest_lblk)
+);
+TRACE_EVENT(xfs_reflink_punch_range,
+       TP_PROTO(struct xfs_inode *ip, xfs_fileoff_t lblk,
+                xfs_extlen_t len),
+       TP_ARGS(ip, lblk, len),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_ino_t, ino)
+               __field(xfs_fileoff_t, lblk)
+               __field(xfs_extlen_t, len)
+       ),
+       TP_fast_assign(
+               __entry->dev = VFS_I(ip)->i_sb->s_dev;
+               __entry->ino = ip->i_ino;
+               __entry->lblk = lblk;
+               __entry->len = len;
+       ),
+       TP_printk("dev %d:%d ino 0x%llx lblk 0x%llx len 0x%x",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->ino,
+                 __entry->lblk,
+                 __entry->len)
+);
+TRACE_EVENT(xfs_reflink_remap,
+       TP_PROTO(struct xfs_inode *ip, xfs_fileoff_t lblk,
+                xfs_extlen_t len, xfs_fsblock_t new_pblk),
+       TP_ARGS(ip, lblk, len, new_pblk),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_ino_t, ino)
+               __field(xfs_fileoff_t, lblk)
+               __field(xfs_extlen_t, len)
+               __field(xfs_fsblock_t, new_pblk)
+       ),
+       TP_fast_assign(
+               __entry->dev = VFS_I(ip)->i_sb->s_dev;
+               __entry->ino = ip->i_ino;
+               __entry->lblk = lblk;
+               __entry->len = len;
+               __entry->new_pblk = new_pblk;
+       ),
+       TP_printk("dev %d:%d ino 0x%llx lblk 0x%llx len 0x%x new_pblk %llu",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->ino,
+                 __entry->lblk,
+                 __entry->len,
+                 __entry->new_pblk)
+);
+DEFINE_DOUBLE_IO_EVENT(xfs_reflink_remap_range);
+DEFINE_INODE_ERROR_EVENT(xfs_reflink_remap_range_error);
+DEFINE_INODE_ERROR_EVENT(xfs_reflink_set_inode_flag_error);
+DEFINE_INODE_ERROR_EVENT(xfs_reflink_update_inode_size_error);
+DEFINE_INODE_ERROR_EVENT(xfs_reflink_reflink_main_loop_error);
+DEFINE_INODE_ERROR_EVENT(xfs_reflink_read_iomap_error);
+DEFINE_INODE_ERROR_EVENT(xfs_reflink_remap_blocks_error);
+DEFINE_INODE_ERROR_EVENT(xfs_reflink_remap_extent_error);
+
+/* dedupe tracepoints */
+DEFINE_DOUBLE_IO_EVENT(xfs_reflink_compare_extents);
+DEFINE_INODE_ERROR_EVENT(xfs_reflink_compare_extents_error);
+
+/* ioctl tracepoints */
+DEFINE_DOUBLE_VFS_IO_EVENT(xfs_ioctl_reflink);
+DEFINE_DOUBLE_VFS_IO_EVENT(xfs_ioctl_clone_range);
+DEFINE_DOUBLE_VFS_IO_EVENT(xfs_ioctl_file_extent_same);
+TRACE_EVENT(xfs_ioctl_clone,
+       TP_PROTO(struct inode *src, struct inode *dest),
+       TP_ARGS(src, dest),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(unsigned long, src_ino)
+               __field(loff_t, src_isize)
+               __field(unsigned long, dest_ino)
+               __field(loff_t, dest_isize)
+       ),
+       TP_fast_assign(
+               __entry->dev = src->i_sb->s_dev;
+               __entry->src_ino = src->i_ino;
+               __entry->src_isize = i_size_read(src);
+               __entry->dest_ino = dest->i_ino;
+               __entry->dest_isize = i_size_read(dest);
+       ),
+       TP_printk("dev %d:%d "
+                 "ino 0x%lx isize 0x%llx -> "
+                 "ino 0x%lx isize 0x%llx\n",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->src_ino,
+                 __entry->src_isize,
+                 __entry->dest_ino,
+                 __entry->dest_isize)
+);
+
+/* unshare tracepoints */
+DEFINE_SIMPLE_IO_EVENT(xfs_reflink_unshare);
+DEFINE_SIMPLE_IO_EVENT(xfs_reflink_cow_eof_block);
+DEFINE_PAGE_EVENT(xfs_reflink_unshare_page);
+DEFINE_INODE_ERROR_EVENT(xfs_reflink_unshare_error);
+DEFINE_INODE_ERROR_EVENT(xfs_reflink_cow_eof_block_error);
+DEFINE_INODE_ERROR_EVENT(xfs_reflink_dirty_page_error);
+
+/* copy on write */
+DEFINE_INODE_IREC_EVENT(xfs_reflink_trim_around_shared);
+DEFINE_INODE_IREC_EVENT(xfs_reflink_cow_alloc);
+DEFINE_INODE_IREC_EVENT(xfs_reflink_cow_found);
+DEFINE_INODE_IREC_EVENT(xfs_reflink_cow_enospc);
+
+DEFINE_RW_EVENT(xfs_reflink_reserve_cow);
+DEFINE_RW_EVENT(xfs_reflink_allocate_cow_range);
+
+DEFINE_INODE_IREC_EVENT(xfs_reflink_bounce_dio_write);
+DEFINE_IOMAP_EVENT(xfs_reflink_find_cow_mapping);
+DEFINE_INODE_IREC_EVENT(xfs_reflink_trim_irec);
+
+DEFINE_SIMPLE_IO_EVENT(xfs_reflink_cancel_cow_range);
+DEFINE_SIMPLE_IO_EVENT(xfs_reflink_end_cow);
+DEFINE_INODE_IREC_EVENT(xfs_reflink_cow_remap);
+DEFINE_INODE_IREC_EVENT(xfs_reflink_cow_remap_piece);
+
+DEFINE_INODE_ERROR_EVENT(xfs_reflink_allocate_cow_range_error);
+DEFINE_INODE_ERROR_EVENT(xfs_reflink_cancel_cow_range_error);
+DEFINE_INODE_ERROR_EVENT(xfs_reflink_end_cow_error);
+
+DEFINE_COW_EVENT(xfs_reflink_fork_buf);
+DEFINE_COW_EVENT(xfs_reflink_finish_fork_buf);
+DEFINE_INODE_ERROR_EVENT(xfs_reflink_fork_buf_error);
+DEFINE_INODE_ERROR_EVENT(xfs_reflink_finish_fork_buf_error);
+
+DEFINE_INODE_EVENT(xfs_reflink_cancel_pending_cow);
+DEFINE_INODE_IREC_EVENT(xfs_reflink_cancel_cow);
+DEFINE_INODE_ERROR_EVENT(xfs_reflink_cancel_pending_cow_error);
+
+/* rmap swapext tracepoints */
+DEFINE_INODE_IREC_EVENT(xfs_swap_extent_rmap_remap);
+DEFINE_INODE_IREC_EVENT(xfs_swap_extent_rmap_remap_piece);
+DEFINE_INODE_ERROR_EVENT(xfs_swap_extent_rmap_error);
+
 #endif /* _TRACE_XFS_H */
 
 #undef TRACE_INCLUDE_PATH