Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xfs: add debug knob to slow down write for fun

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>

+60 -3
+3 -1
fs/xfs/libxfs/xfs_errortag.h
··· 62 62 #define XFS_ERRTAG_DA_LEAF_SPLIT 40 63 63 #define XFS_ERRTAG_ATTR_LEAF_TO_NODE 41 64 64 #define XFS_ERRTAG_WB_DELAY_MS 42 65 - #define XFS_ERRTAG_MAX 43 65 + #define XFS_ERRTAG_WRITE_DELAY_MS 43 66 + #define XFS_ERRTAG_MAX 44 66 67 67 68 /* 68 69 * Random factors for above tags, 1 means always, 2 means 1/2 time, etc. ··· 110 109 #define XFS_RANDOM_DA_LEAF_SPLIT 1 111 110 #define XFS_RANDOM_ATTR_LEAF_TO_NODE 1 112 111 #define XFS_RANDOM_WB_DELAY_MS 3000 112 + #define XFS_RANDOM_WRITE_DELAY_MS 3000 113 113 114 114 #endif /* __XFS_ERRORTAG_H_ */
+3
fs/xfs/xfs_error.c
··· 61 61 XFS_RANDOM_DA_LEAF_SPLIT, 62 62 XFS_RANDOM_ATTR_LEAF_TO_NODE, 63 63 XFS_RANDOM_WB_DELAY_MS, 64 + XFS_RANDOM_WRITE_DELAY_MS, 64 65 }; 65 66 66 67 struct xfs_errortag_attr { ··· 178 177 XFS_ERRORTAG_ATTR_RW(da_leaf_split, XFS_ERRTAG_DA_LEAF_SPLIT); 179 178 XFS_ERRORTAG_ATTR_RW(attr_leaf_to_node, XFS_ERRTAG_ATTR_LEAF_TO_NODE); 180 179 XFS_ERRORTAG_ATTR_RW(wb_delay_ms, XFS_ERRTAG_WB_DELAY_MS); 180 + XFS_ERRORTAG_ATTR_RW(write_delay_ms, XFS_ERRTAG_WRITE_DELAY_MS); 181 181 182 182 static struct attribute *xfs_errortag_attrs[] = { 183 183 XFS_ERRORTAG_ATTR_LIST(noerror), ··· 223 221 XFS_ERRORTAG_ATTR_LIST(da_leaf_split), 224 222 XFS_ERRORTAG_ATTR_LIST(attr_leaf_to_node), 225 223 XFS_ERRORTAG_ATTR_LIST(wb_delay_ms), 224 + XFS_ERRORTAG_ATTR_LIST(write_delay_ms), 226 225 NULL, 227 226 }; 228 227 ATTRIBUTE_GROUPS(xfs_errortag);
+12 -2
fs/xfs/xfs_iomap.c
··· 27 27 #include "xfs_dquot_item.h" 28 28 #include "xfs_dquot.h" 29 29 #include "xfs_reflink.h" 30 + #include "xfs_error.h" 31 + #include "xfs_errortag.h" 30 32 31 33 #define XFS_ALLOC_ALIGN(mp, off) \ 32 34 (((off) >> mp->m_allocsize_log) << mp->m_allocsize_log) ··· 73 71 struct inode *inode, 74 72 const struct iomap *iomap) 75 73 { 76 - return iomap->validity_cookie == 77 - xfs_iomap_inode_sequence(XFS_I(inode), iomap->flags); 74 + struct xfs_inode *ip = XFS_I(inode); 75 + 76 + if (iomap->validity_cookie != 77 + xfs_iomap_inode_sequence(ip, iomap->flags)) { 78 + trace_xfs_iomap_invalid(ip, iomap); 79 + return false; 80 + } 81 + 82 + XFS_ERRORTAG_DELAY(ip->i_mount, XFS_ERRTAG_WRITE_DELAY_MS); 83 + return true; 78 84 } 79 85 80 86 const struct iomap_page_ops xfs_iomap_page_ops = {
+42
fs/xfs/xfs_trace.h
··· 3396 3396 DEFINE_WB_INVALID_EVENT(xfs_wb_cow_iomap_invalid); 3397 3397 DEFINE_WB_INVALID_EVENT(xfs_wb_data_iomap_invalid); 3398 3398 3399 + DECLARE_EVENT_CLASS(xfs_iomap_invalid_class, 3400 + TP_PROTO(struct xfs_inode *ip, const struct iomap *iomap), 3401 + TP_ARGS(ip, iomap), 3402 + TP_STRUCT__entry( 3403 + __field(dev_t, dev) 3404 + __field(xfs_ino_t, ino) 3405 + __field(u64, addr) 3406 + __field(loff_t, pos) 3407 + __field(u64, len) 3408 + __field(u64, validity_cookie) 3409 + __field(u64, inodeseq) 3410 + __field(u16, type) 3411 + __field(u16, flags) 3412 + ), 3413 + TP_fast_assign( 3414 + __entry->dev = VFS_I(ip)->i_sb->s_dev; 3415 + __entry->ino = ip->i_ino; 3416 + __entry->addr = iomap->addr; 3417 + __entry->pos = iomap->offset; 3418 + __entry->len = iomap->length; 3419 + __entry->validity_cookie = iomap->validity_cookie; 3420 + __entry->type = iomap->type; 3421 + __entry->flags = iomap->flags; 3422 + __entry->inodeseq = xfs_iomap_inode_sequence(ip, iomap->flags); 3423 + ), 3424 + 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", 3425 + MAJOR(__entry->dev), MINOR(__entry->dev), 3426 + __entry->ino, 3427 + __entry->pos, 3428 + __entry->addr, 3429 + __entry->len, 3430 + __entry->type, 3431 + __entry->flags, 3432 + __entry->validity_cookie, 3433 + __entry->inodeseq) 3434 + ); 3435 + #define DEFINE_IOMAP_INVALID_EVENT(name) \ 3436 + DEFINE_EVENT(xfs_iomap_invalid_class, name, \ 3437 + TP_PROTO(struct xfs_inode *ip, const struct iomap *iomap), \ 3438 + TP_ARGS(ip, iomap)) 3439 + DEFINE_IOMAP_INVALID_EVENT(xfs_iomap_invalid); 3440 + 3399 3441 /* refcount/reflink tracepoint definitions */ 3400 3442 3401 3443 /* reflink tracepoints */