[Top] [All Lists]

[PATCH 1/6] xfs: kill buffers over failed write ranges properly

To: xfs@xxxxxxxxxxx
Subject: [PATCH 1/6] xfs: kill buffers over failed write ranges properly
From: Dave Chinner <david@xxxxxxxxxxxxx>
Date: Fri, 21 Mar 2014 21:11:45 +1100
Cc: Al@xxxxxxxxxxxxxxxxxxxxxxx, Viro@xxxxxxxxxxxxxxxxxxxxxxx, <viro@xxxxxxxxxxxxxxxxxx>
Delivered-to: xfs@xxxxxxxxxxx
In-reply-to: <1395396710-3824-1-git-send-email-david@xxxxxxxxxxxxx>
References: <1395396710-3824-1-git-send-email-david@xxxxxxxxxxxxx>
From: Dave Chinner <dchinner@xxxxxxxxxx>

When a write fails, if we don't clear the delalloc flags from the
buffers over the failed range, they can persist beyond EOF and cause
problems. writeback will see the pages int eh page cache, see they
are dirty and continually retry the write, assuming that the page
beyond EOF is just racing with a truncate. The page will eventually
be released due to some other operation (e.g. direct IO), and it
will not pass through invalidation because it is dirty. Hence it
will be released with buffer_delay set on it, and trigger warnings
in xfs_vm_releasepage() and assert fail in xfs_file_aio_write_direct
because invalidation failed and we didn't write the corect amount.

This causes failures on block size < page size filesystems in fsx
and fsstress workloads run by xfstests.

Fix it by completely trashing any state on the buffer that could be
used to imply that it contains valid data when the delalloc range
over the buffer is punched out during the failed write handling.

Signed-off-by: Dave Chinner <dchinner@xxxxxxxxxx>
 fs/xfs/xfs_aops.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 98016b3..e810243 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -1566,6 +1566,16 @@ xfs_vm_write_failed(
                xfs_vm_kill_delalloc_range(inode, block_offset,
                                           block_offset + bh->b_size);
+               /*
+                * This buffer does not contain data anymore. make sure anyone
+                * who finds it knows that for certain.
+                */
+               clear_buffer_delay(bh);
+               clear_buffer_uptodate(bh);
+               clear_buffer_mapped(bh);
+               clear_buffer_new(bh);
+               clear_buffer_dirty(bh);

<Prev in Thread] Current Thread [Next in Thread>