xfs: add debug knob to slow down write for fun
authorDarrick J. Wong <djwong@kernel.org>
Tue, 29 Nov 2022 01:24:36 +0000 (17:24 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 29 Nov 2022 01:54:49 +0000 (17:54 -0800)
Add a new error injection knob so that we can arbitrarily slow down
pagecache writes to test for race conditions and aberrant reclaim
behavior if the writeback mechanisms are slow to issue writeback.  This
will enable functional testing for the ifork sequence counters
introduced in commit 304a68b9c63b ("xfs: use iomap_valid method to
detect stale cached iomaps") that fixes write racing with reclaim
writeback.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
fs/xfs/libxfs/xfs_errortag.h
fs/xfs/xfs_error.c
fs/xfs/xfs_iomap.c
fs/xfs/xfs_trace.h

index f5f629174ecad6b686f55d2d82cfc1e1cc4b6398..01a9e86b303790f82d7fce5525ef40085a4b2bb2 100644 (file)
@@ -62,7 +62,8 @@
 #define XFS_ERRTAG_DA_LEAF_SPLIT                       40
 #define XFS_ERRTAG_ATTR_LEAF_TO_NODE                   41
 #define XFS_ERRTAG_WB_DELAY_MS                         42
-#define XFS_ERRTAG_MAX                                 43
+#define XFS_ERRTAG_WRITE_DELAY_MS                      43
+#define XFS_ERRTAG_MAX                                 44
 
 /*
  * Random factors for above tags, 1 means always, 2 means 1/2 time, etc.
 #define XFS_RANDOM_DA_LEAF_SPLIT                       1
 #define XFS_RANDOM_ATTR_LEAF_TO_NODE                   1
 #define XFS_RANDOM_WB_DELAY_MS                         3000
+#define XFS_RANDOM_WRITE_DELAY_MS                      3000
 
 #endif /* __XFS_ERRORTAG_H_ */
index 2d6e3c718e03d08d97b6a55e6cdba199dff3633f..713341d246d1844c61b12f7ffe0927821c24bc79 100644 (file)
@@ -61,6 +61,7 @@ static unsigned int xfs_errortag_random_default[] = {
        XFS_RANDOM_DA_LEAF_SPLIT,
        XFS_RANDOM_ATTR_LEAF_TO_NODE,
        XFS_RANDOM_WB_DELAY_MS,
+       XFS_RANDOM_WRITE_DELAY_MS,
 };
 
 struct xfs_errortag_attr {
@@ -177,6 +178,7 @@ XFS_ERRORTAG_ATTR_RW(larp,          XFS_ERRTAG_LARP);
 XFS_ERRORTAG_ATTR_RW(da_leaf_split,    XFS_ERRTAG_DA_LEAF_SPLIT);
 XFS_ERRORTAG_ATTR_RW(attr_leaf_to_node,        XFS_ERRTAG_ATTR_LEAF_TO_NODE);
 XFS_ERRORTAG_ATTR_RW(wb_delay_ms,      XFS_ERRTAG_WB_DELAY_MS);
+XFS_ERRORTAG_ATTR_RW(write_delay_ms,   XFS_ERRTAG_WRITE_DELAY_MS);
 
 static struct attribute *xfs_errortag_attrs[] = {
        XFS_ERRORTAG_ATTR_LIST(noerror),
@@ -221,6 +223,7 @@ static struct attribute *xfs_errortag_attrs[] = {
        XFS_ERRORTAG_ATTR_LIST(da_leaf_split),
        XFS_ERRORTAG_ATTR_LIST(attr_leaf_to_node),
        XFS_ERRORTAG_ATTR_LIST(wb_delay_ms),
+       XFS_ERRORTAG_ATTR_LIST(write_delay_ms),
        NULL,
 };
 ATTRIBUTE_GROUPS(xfs_errortag);
index 1bdd7afc1010801b06e3e2d674b18987cb23a4d3..1005f1e365454c5be3a8972957275df5ec1517f3 100644 (file)
@@ -27,6 +27,8 @@
 #include "xfs_dquot_item.h"
 #include "xfs_dquot.h"
 #include "xfs_reflink.h"
+#include "xfs_error.h"
+#include "xfs_errortag.h"
 
 #define XFS_ALLOC_ALIGN(mp, off) \
        (((off) >> mp->m_allocsize_log) << mp->m_allocsize_log)
@@ -71,8 +73,16 @@ xfs_iomap_valid(
        struct inode            *inode,
        const struct iomap      *iomap)
 {
-       return iomap->validity_cookie ==
-                       xfs_iomap_inode_sequence(XFS_I(inode), iomap->flags);
+       struct xfs_inode        *ip = XFS_I(inode);
+
+       if (iomap->validity_cookie !=
+                       xfs_iomap_inode_sequence(ip, iomap->flags)) {
+               trace_xfs_iomap_invalid(ip, iomap);
+               return false;
+       }
+
+       XFS_ERRORTAG_DELAY(ip->i_mount, XFS_ERRTAG_WRITE_DELAY_MS);
+       return true;
 }
 
 const struct iomap_page_ops xfs_iomap_page_ops = {
index c9ada9577a4a7a35110853097cfede903a1792ff..421d1e504ac43a4fc01f898fca0662a77c5c6426 100644 (file)
@@ -3396,6 +3396,48 @@ DEFINE_EVENT(xfs_wb_invalid_class, name, \
 DEFINE_WB_INVALID_EVENT(xfs_wb_cow_iomap_invalid);
 DEFINE_WB_INVALID_EVENT(xfs_wb_data_iomap_invalid);
 
+DECLARE_EVENT_CLASS(xfs_iomap_invalid_class,
+       TP_PROTO(struct xfs_inode *ip, const struct iomap *iomap),
+       TP_ARGS(ip, iomap),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_ino_t, ino)
+               __field(u64, addr)
+               __field(loff_t, pos)
+               __field(u64, len)
+               __field(u64, validity_cookie)
+               __field(u64, inodeseq)
+               __field(u16, type)
+               __field(u16, flags)
+       ),
+       TP_fast_assign(
+               __entry->dev = VFS_I(ip)->i_sb->s_dev;
+               __entry->ino = ip->i_ino;
+               __entry->addr = iomap->addr;
+               __entry->pos = iomap->offset;
+               __entry->len = iomap->length;
+               __entry->validity_cookie = iomap->validity_cookie;
+               __entry->type = iomap->type;
+               __entry->flags = iomap->flags;
+               __entry->inodeseq = xfs_iomap_inode_sequence(ip, iomap->flags);
+       ),
+       TP_printk("dev %d:%d ino 0x%llx pos 0x%llx addr 0x%llx bytecount 0x%llx type 0x%x flags 0x%x validity_cookie 0x%llx inodeseq 0x%llx",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->ino,
+                 __entry->pos,
+                 __entry->addr,
+                 __entry->len,
+                 __entry->type,
+                 __entry->flags,
+                 __entry->validity_cookie,
+                 __entry->inodeseq)
+);
+#define DEFINE_IOMAP_INVALID_EVENT(name) \
+DEFINE_EVENT(xfs_iomap_invalid_class, name, \
+       TP_PROTO(struct xfs_inode *ip, const struct iomap *iomap), \
+       TP_ARGS(ip, iomap))
+DEFINE_IOMAP_INVALID_EVENT(xfs_iomap_invalid);
+
 /* refcount/reflink tracepoint definitions */
 
 /* reflink tracepoints */