@@ -1061,6 +1061,37 @@ xfs_flush_unmap_range(
return 0;
}
+/*
+ * Ensure that the specified range is all zeros.
+ * Unmapped or unwritten blocks are left alone by the iomap mechanism,
+ * as they already return zero on read.
+ * This will happily extend i_size if asked to do so.
+ */
+static int
+xfs_zero_range(
+ struct xfs_inode *ip,
+ xfs_off_t offset,
+ xfs_off_t len)
+{
+ int error;
+
+ error = iomap_zero_range(VFS_I(ip), offset, len, NULL, &xfs_iomap_ops);
+ if (error)
+ return error;
+ /*
+ * If we zeroed right up to EOF and EOF straddles a page boundary we
+ * must make sure that the post-EOF area is also zeroed because the
+ * page could be mmap'd and iomap_zero_range doesn't do that for us.
+ * Writeback of the eof page will do this, albeit clumsily.
+ */
+ if (offset + len >= XFS_ISIZE(ip) && offset_in_page(offset + len) > 0) {
+ error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
+ round_down(offset + len, PAGE_SIZE), LLONG_MAX);
+ }
+
+ return error;
+}
+
int
xfs_free_file_space(
struct xfs_inode *ip,
@@ -1101,28 +1132,15 @@ xfs_free_file_space(
}
/*
- * Now that we've unmap all full blocks we'll have to zero out any
- * partial block at the beginning and/or end. iomap_zero_range is smart
- * enough to skip any holes, including those we just created, but we
- * must take care not to zero beyond EOF and enlarge i_size.
- */
- if (offset >= XFS_ISIZE(ip))
- return 0;
- if (offset + len > XFS_ISIZE(ip))
- len = XFS_ISIZE(ip) - offset;
- error = iomap_zero_range(VFS_I(ip), offset, len, NULL, &xfs_iomap_ops);
- if (error)
- return error;
-
- /*
- * If we zeroed right up to EOF and EOF straddles a page boundary we
- * must make sure that the post-EOF area is also zeroed because the
- * page could be mmap'd and iomap_zero_range doesn't do that for us.
- * Writeback of the eof page will do this, albeit clumsily.
+ * Now that we've unmapped all full blocks we'll have to zero out any
+ * partial block at the beginning and/or end. xfs_zero_range is smart
+ * enough to skip any holes, including those we just created. We don't
+ * want to zero beyond EOF and enlarge i_size.
*/
- if (offset + len >= XFS_ISIZE(ip) && offset_in_page(offset + len) > 0) {
- error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
- round_down(offset + len, PAGE_SIZE), LLONG_MAX);
+ if (offset < XFS_ISIZE(ip)) {
+ if (offset + len > XFS_ISIZE(ip))
+ len = XFS_ISIZE(ip) - offset;
+ error = xfs_zero_range(ip, offset, len);
}
return error;
Factor out the range zeroing part of xfs_free_file_space into a new function, xfs_zero_range, which is a wrapper around iomap_zero_range + EOF handling. Signed-off-by: Eric Sandeen <sandeen@redhat.com> ---