Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f69f578 authored by Dave Chinner's avatar Dave Chinner Committed by Dave Chinner
Browse files

xfs: add DAX block zeroing support



Add initial support for DAX block zeroing operations to XFS. DAX
cannot use buffered IO through the page cache for zeroing, nor do we
need to issue IO for uncached block zeroing. In both cases, we can
simply call out to the dax block zeroing function.

Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
parent 6b698ede
Loading
Loading
Loading
Loading
+19 −4
Original line number Diff line number Diff line
@@ -1133,14 +1133,29 @@ xfs_zero_remaining_bytes(
			break;
		ASSERT(imap.br_blockcount >= 1);
		ASSERT(imap.br_startoff == offset_fsb);
		ASSERT(imap.br_startblock != DELAYSTARTBLOCK);

		if (imap.br_startblock == HOLESTARTBLOCK ||
		    imap.br_state == XFS_EXT_UNWRITTEN) {
			/* skip the entire extent */
			lastoffset = XFS_FSB_TO_B(mp, imap.br_startoff +
						      imap.br_blockcount) - 1;
			continue;
		}

		lastoffset = XFS_FSB_TO_B(mp, imap.br_startoff + 1) - 1;
		if (lastoffset > endoff)
			lastoffset = endoff;
		if (imap.br_startblock == HOLESTARTBLOCK)
			continue;
		ASSERT(imap.br_startblock != DELAYSTARTBLOCK);
		if (imap.br_state == XFS_EXT_UNWRITTEN)

		/* DAX can just zero the backing device directly */
		if (IS_DAX(VFS_I(ip))) {
			error = dax_zero_page_range(VFS_I(ip), offset,
						    lastoffset - offset + 1,
						    xfs_get_blocks_direct);
			if (error)
				return error;
			continue;
		}

		error = xfs_buf_read_uncached(XFS_IS_REALTIME_INODE(ip) ?
				mp->m_rtdev_targp : mp->m_ddev_targp,
+27 −18
Original line number Diff line number Diff line
@@ -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,6 +110,12 @@ xfs_iozero(
		if (bytes > count)
			bytes = count;

		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);
@@ -116,12 +124,13 @@ xfs_iozero(

			zero_user(page, offset, bytes);

		status = pagecache_write_end(NULL, mapping, pos, bytes, bytes,
					page, fsdata);
			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);