Commit 9dbddd7b authored by Brian Foster's avatar Brian Foster Committed by Darrick J. Wong

xfs: resurrect debug mode drop buffered writes mechanism

A debug mode write failure mechanism was introduced to XFS in commit
801cc4e1 ("xfs: debug mode forced buffered write failure") to
facilitate targeted testing of delalloc indirect reservation management
from userspace. This code was subsequently rendered ineffective by the
move to iomap based buffered writes in commit 68a9f5e7 ("xfs:
implement iomap based buffered write path"). This likely went unnoticed
because the associated userspace code had not made it into xfstests.

Resurrect this mechanism to facilitate effective indlen reservation
testing from xfstests. The move to iomap based buffered writes relocated
the hook this mechanism needs to return write failure from XFS to
generic code. The failure trigger must remain in XFS. Given that
limitation, convert this from a write failure mechanism to one that
simply drops writes without returning failure to userspace. Rename all
"fail_writes" references to "drop_writes" to illustrate the point. This
is more hacky than preferred, but still triggers the XFS error handling
behavior required to drive the indlen tests. This is only available in
DEBUG mode and for testing purposes only.
Signed-off-by: default avatarBrian Foster <bfoster@redhat.com>
Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
parent fa7f138a
...@@ -1078,6 +1078,10 @@ xfs_file_iomap_end_delalloc( ...@@ -1078,6 +1078,10 @@ xfs_file_iomap_end_delalloc(
xfs_fileoff_t end_fsb; xfs_fileoff_t end_fsb;
int error = 0; int error = 0;
/* behave as if the write failed if drop writes is enabled */
if (xfs_mp_drop_writes(mp))
written = 0;
/* /*
* start_fsb refers to the first unused block after a short write. If * start_fsb refers to the first unused block after a short write. If
* nothing was written, round offset down to point at the first block in * nothing was written, round offset down to point at the first block in
......
...@@ -200,11 +200,12 @@ typedef struct xfs_mount { ...@@ -200,11 +200,12 @@ typedef struct xfs_mount {
/* /*
* DEBUG mode instrumentation to test and/or trigger delayed allocation * DEBUG mode instrumentation to test and/or trigger delayed allocation
* block killing in the event of failed writes. When enabled, all * block killing in the event of failed writes. When enabled, all
* buffered writes are forced to fail. All delalloc blocks in the range * buffered writes are silenty dropped and handled as if they failed.
* of the write (including pre-existing delalloc blocks!) are tossed as * All delalloc blocks in the range of the write (including pre-existing
* part of the write failure error handling sequence. * delalloc blocks!) are tossed as part of the write failure error
* handling sequence.
*/ */
bool m_fail_writes; bool m_drop_writes;
#endif #endif
} xfs_mount_t; } xfs_mount_t;
...@@ -325,13 +326,13 @@ xfs_daddr_to_agbno(struct xfs_mount *mp, xfs_daddr_t d) ...@@ -325,13 +326,13 @@ xfs_daddr_to_agbno(struct xfs_mount *mp, xfs_daddr_t d)
#ifdef DEBUG #ifdef DEBUG
static inline bool static inline bool
xfs_mp_fail_writes(struct xfs_mount *mp) xfs_mp_drop_writes(struct xfs_mount *mp)
{ {
return mp->m_fail_writes; return mp->m_drop_writes;
} }
#else #else
static inline bool static inline bool
xfs_mp_fail_writes(struct xfs_mount *mp) xfs_mp_drop_writes(struct xfs_mount *mp)
{ {
return 0; return 0;
} }
......
...@@ -93,7 +93,7 @@ to_mp(struct kobject *kobject) ...@@ -93,7 +93,7 @@ to_mp(struct kobject *kobject)
#ifdef DEBUG #ifdef DEBUG
STATIC ssize_t STATIC ssize_t
fail_writes_store( drop_writes_store(
struct kobject *kobject, struct kobject *kobject,
const char *buf, const char *buf,
size_t count) size_t count)
...@@ -107,9 +107,9 @@ fail_writes_store( ...@@ -107,9 +107,9 @@ fail_writes_store(
return ret; return ret;
if (val == 1) if (val == 1)
mp->m_fail_writes = true; mp->m_drop_writes = true;
else if (val == 0) else if (val == 0)
mp->m_fail_writes = false; mp->m_drop_writes = false;
else else
return -EINVAL; return -EINVAL;
...@@ -117,21 +117,21 @@ fail_writes_store( ...@@ -117,21 +117,21 @@ fail_writes_store(
} }
STATIC ssize_t STATIC ssize_t
fail_writes_show( drop_writes_show(
struct kobject *kobject, struct kobject *kobject,
char *buf) char *buf)
{ {
struct xfs_mount *mp = to_mp(kobject); struct xfs_mount *mp = to_mp(kobject);
return snprintf(buf, PAGE_SIZE, "%d\n", mp->m_fail_writes ? 1 : 0); return snprintf(buf, PAGE_SIZE, "%d\n", mp->m_drop_writes ? 1 : 0);
} }
XFS_SYSFS_ATTR_RW(fail_writes); XFS_SYSFS_ATTR_RW(drop_writes);
#endif /* DEBUG */ #endif /* DEBUG */
static struct attribute *xfs_mp_attrs[] = { static struct attribute *xfs_mp_attrs[] = {
#ifdef DEBUG #ifdef DEBUG
ATTR_LIST(fail_writes), ATTR_LIST(drop_writes),
#endif #endif
NULL, NULL,
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment