|
@@ -79,14 +79,15 @@ xfs_rw_ilock_demote(
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * xfs_iozero
|
|
|
+ * xfs_iozero clears the specified range supplied via the page cache (except in
|
|
|
+ * the DAX case). Writes through the page cache will allocate blocks over holes,
|
|
|
+ * though the callers usually map the holes first and avoid them. If a block is
|
|
|
+ * not completely zeroed, then it will be read from disk before being partially
|
|
|
+ * zeroed.
|
|
|
*
|
|
|
- * xfs_iozero clears the specified range of buffer supplied,
|
|
|
- * and marks all the affected blocks as valid and modified. If
|
|
|
- * an affected block is not allocated, it will be allocated. If
|
|
|
- * an affected block is not completely overwritten, and is not
|
|
|
- * valid before the operation, it will be read from disk before
|
|
|
- * being partially zeroed.
|
|
|
+ * In the DAX case, we can just directly write to the underlying pages. This
|
|
|
+ * will not allocate blocks, but will avoid holes and unwritten extents and so
|
|
|
+ * not do unnecessary work.
|
|
|
*/
|
|
|
int
|
|
|
xfs_iozero(
|
|
@@ -96,7 +97,8 @@ xfs_iozero(
|
|
|
{
|
|
|
struct page *page;
|
|
|
struct address_space *mapping;
|
|
|
- int status;
|
|
|
+ int status = 0;
|
|
|
+
|
|
|
|
|
|
mapping = VFS_I(ip)->i_mapping;
|
|
|
do {
|
|
@@ -108,20 +110,27 @@ xfs_iozero(
|
|
|
if (bytes > count)
|
|
|
bytes = count;
|
|
|
|
|
|
- status = pagecache_write_begin(NULL, mapping, pos, bytes,
|
|
|
- AOP_FLAG_UNINTERRUPTIBLE,
|
|
|
- &page, &fsdata);
|
|
|
- if (status)
|
|
|
- break;
|
|
|
+ if (IS_DAX(VFS_I(ip))) {
|
|
|
+ status = dax_zero_page_range(VFS_I(ip), pos, bytes,
|
|
|
+ xfs_get_blocks_direct);
|
|
|
+ if (status)
|
|
|
+ break;
|
|
|
+ } else {
|
|
|
+ status = pagecache_write_begin(NULL, mapping, pos, bytes,
|
|
|
+ AOP_FLAG_UNINTERRUPTIBLE,
|
|
|
+ &page, &fsdata);
|
|
|
+ if (status)
|
|
|
+ break;
|
|
|
|
|
|
- zero_user(page, offset, bytes);
|
|
|
+ zero_user(page, offset, bytes);
|
|
|
|
|
|
- status = pagecache_write_end(NULL, mapping, pos, bytes, bytes,
|
|
|
- page, fsdata);
|
|
|
- WARN_ON(status <= 0); /* can't return less than zero! */
|
|
|
+ status = pagecache_write_end(NULL, mapping, pos, bytes,
|
|
|
+ bytes, page, fsdata);
|
|
|
+ WARN_ON(status <= 0); /* can't return less than zero! */
|
|
|
+ status = 0;
|
|
|
+ }
|
|
|
pos += bytes;
|
|
|
count -= bytes;
|
|
|
- status = 0;
|
|
|
} while (count);
|
|
|
|
|
|
return (-status);
|