aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2014-04-14 04:11:58 -0400
committerDave Chinner <david@fromorbit.com>2014-04-14 04:11:58 -0400
commit4ab9ed578e82851645f3dd69d36d91ae77564d6c (patch)
tree3910fde13741b8abf9657605f246d762881fc379 /fs
parentc9eaa447e77efe77b7fa4c953bd62de8297fd6c5 (diff)
xfs: kill buffers over failed write ranges properly
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 in the 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@redhat.com> Tested-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/xfs_aops.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 75df77d09f75..282c726d04d0 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -1566,6 +1566,16 @@ xfs_vm_write_failed(
1566 1566
1567 xfs_vm_kill_delalloc_range(inode, block_offset, 1567 xfs_vm_kill_delalloc_range(inode, block_offset,
1568 block_offset + bh->b_size); 1568 block_offset + bh->b_size);
1569
1570 /*
1571 * This buffer does not contain data anymore. make sure anyone
1572 * who finds it knows that for certain.
1573 */
1574 clear_buffer_delay(bh);
1575 clear_buffer_uptodate(bh);
1576 clear_buffer_mapped(bh);
1577 clear_buffer_new(bh);
1578 clear_buffer_dirty(bh);
1569 } 1579 }
1570 1580
1571} 1581}