Commit cd14f15b authored by Darrick J. Wong's avatar Darrick J. Wong
Browse files

Merge tag 'iomap-write-race-testing-6.2_2022-11-30' of...

Merge tag 'iomap-write-race-testing-6.2_2022-11-30' of git://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux

 into xfs-6.2-mergeC

xfs: add knobs for testing iomap write race fixes

This series is a followup to Dave Chinner's series entitled
"xfs, iomap: fix data corruption due to stale cached iomaps".
The two patches here add debugging knobs to introduce artificial delays
into the pagecache write and writeback code to facilitate testing of the
iomap invalidation code.  New tracepoints are also introduced so that
fstests can look for the invalidations.

Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>

* tag 'iomap-write-race-testing-6.2_2022-11-30' of git://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux:
  xfs: add debug knob to slow down write for fun
  xfs: add debug knob to slow down writeback for fun
parents 7dd73802 254e3459
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -61,7 +61,9 @@
#define XFS_ERRTAG_LARP					39
#define XFS_ERRTAG_DA_LEAF_SPLIT			40
#define XFS_ERRTAG_ATTR_LEAF_TO_NODE			41
#define XFS_ERRTAG_MAX					42
#define XFS_ERRTAG_WB_DELAY_MS				42
#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.
@@ -107,5 +109,7 @@
#define XFS_RANDOM_LARP					1
#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_ */
+12 −2
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
#include "xfs_bmap.h"
#include "xfs_bmap_util.h"
#include "xfs_reflink.h"
#include "xfs_errortag.h"
#include "xfs_error.h"

struct xfs_writepage_ctx {
	struct iomap_writepage_ctx ctx;
@@ -217,11 +219,17 @@ xfs_imap_valid(
	 * checked (and found nothing at this offset) could have added
	 * overlapping blocks.
	 */
	if (XFS_WPC(wpc)->data_seq != READ_ONCE(ip->i_df.if_seq))
	if (XFS_WPC(wpc)->data_seq != READ_ONCE(ip->i_df.if_seq)) {
		trace_xfs_wb_data_iomap_invalid(ip, &wpc->iomap,
				XFS_WPC(wpc)->data_seq, XFS_DATA_FORK);
		return false;
	}
	if (xfs_inode_has_cow_data(ip) &&
	    XFS_WPC(wpc)->cow_seq != READ_ONCE(ip->i_cowfp->if_seq))
	    XFS_WPC(wpc)->cow_seq != READ_ONCE(ip->i_cowfp->if_seq)) {
		trace_xfs_wb_cow_iomap_invalid(ip, &wpc->iomap,
				XFS_WPC(wpc)->cow_seq, XFS_COW_FORK);
		return false;
	}
	return true;
}

@@ -285,6 +293,8 @@ xfs_map_blocks(
	if (xfs_is_shutdown(mp))
		return -EIO;

	XFS_ERRORTAG_DELAY(mp, XFS_ERRTAG_WB_DELAY_MS);

	/*
	 * COW fork blocks can overlap data fork blocks even if the blocks
	 * aren't shared.  COW I/O always takes precedent, so we must always
+19 −0
Original line number Diff line number Diff line
@@ -60,6 +60,8 @@ static unsigned int xfs_errortag_random_default[] = {
	XFS_RANDOM_LARP,
	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 {
@@ -175,6 +177,8 @@ XFS_ERRORTAG_ATTR_RW(ag_resv_fail, XFS_ERRTAG_AG_RESV_FAIL);
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),
@@ -218,6 +222,8 @@ static struct attribute *xfs_errortag_attrs[] = {
	XFS_ERRORTAG_ATTR_LIST(larp),
	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);
@@ -267,6 +273,19 @@ xfs_errortag_valid(
	return true;
}

bool
xfs_errortag_enabled(
	struct xfs_mount	*mp,
	unsigned int		tag)
{
	if (!mp->m_errortag)
		return false;
	if (!xfs_errortag_valid(tag))
		return false;

	return mp->m_errortag[tag] != 0;
}

bool
xfs_errortag_test(
	struct xfs_mount	*mp,
+13 −0
Original line number Diff line number Diff line
@@ -45,6 +45,18 @@ extern bool xfs_errortag_test(struct xfs_mount *mp, const char *expression,
		const char *file, int line, unsigned int error_tag);
#define XFS_TEST_ERROR(expr, mp, tag)		\
	((expr) || xfs_errortag_test((mp), #expr, __FILE__, __LINE__, (tag)))
bool xfs_errortag_enabled(struct xfs_mount *mp, unsigned int tag);
#define XFS_ERRORTAG_DELAY(mp, tag)		\
	do { \
		might_sleep(); \
		if (!xfs_errortag_enabled((mp), (tag))) \
			break; \
		xfs_warn_ratelimited((mp), \
"Injecting %ums delay at file %s, line %d, on filesystem \"%s\"", \
				(mp)->m_errortag[(tag)], __FILE__, __LINE__, \
				(mp)->m_super->s_id); \
		mdelay((mp)->m_errortag[(tag)]); \
	} while (0)

extern int xfs_errortag_get(struct xfs_mount *mp, unsigned int error_tag);
extern int xfs_errortag_set(struct xfs_mount *mp, unsigned int error_tag,
@@ -55,6 +67,7 @@ extern int xfs_errortag_clearall(struct xfs_mount *mp);
#define xfs_errortag_init(mp)			(0)
#define xfs_errortag_del(mp)
#define XFS_TEST_ERROR(expr, mp, tag)		(expr)
#define XFS_ERRORTAG_DELAY(mp, tag)		((void)0)
#define xfs_errortag_set(mp, tag, val)		(ENOSYS)
#define xfs_errortag_add(mp, tag)		(ENOSYS)
#define xfs_errortag_clearall(mp)		(ENOSYS)
+12 −2
Original line number Diff line number Diff line
@@ -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 = {
Loading