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

Commit 6c31f495 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Dave Chinner
Browse files

xfs: use iomap to implement DAX



Another users of buffer_heads bytes the dust.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarRoss Zwisler <ross.zwisler@linux.intel.com>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
parent e372843a
Loading
Loading
Loading
Loading
+17 −44
Original line number Original line Diff line number Diff line
@@ -332,10 +332,7 @@ xfs_file_dax_read(
	struct kiocb		*iocb,
	struct kiocb		*iocb,
	struct iov_iter		*to)
	struct iov_iter		*to)
{
{
	struct address_space	*mapping = iocb->ki_filp->f_mapping;
	struct xfs_inode	*ip = XFS_I(iocb->ki_filp->f_mapping->host);
	struct inode		*inode = mapping->host;
	struct xfs_inode	*ip = XFS_I(inode);
	struct iov_iter		data = *to;
	size_t			count = iov_iter_count(to);
	size_t			count = iov_iter_count(to);
	ssize_t			ret = 0;
	ssize_t			ret = 0;


@@ -345,11 +342,7 @@ xfs_file_dax_read(
		return 0; /* skip atime */
		return 0; /* skip atime */


	xfs_rw_ilock(ip, XFS_IOLOCK_SHARED);
	xfs_rw_ilock(ip, XFS_IOLOCK_SHARED);
	ret = dax_do_io(iocb, inode, &data, xfs_get_blocks_direct, NULL, 0);
	ret = iomap_dax_rw(iocb, to, &xfs_iomap_ops);
	if (ret > 0) {
		iocb->ki_pos += ret;
		iov_iter_advance(to, ret);
	}
	xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED);
	xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED);


	file_accessed(iocb->ki_filp);
	file_accessed(iocb->ki_filp);
@@ -711,52 +704,32 @@ xfs_file_dax_write(
	struct kiocb		*iocb,
	struct kiocb		*iocb,
	struct iov_iter		*from)
	struct iov_iter		*from)
{
{
	struct address_space	*mapping = iocb->ki_filp->f_mapping;
	struct inode		*inode = iocb->ki_filp->f_mapping->host;
	struct inode		*inode = mapping->host;
	struct xfs_inode	*ip = XFS_I(inode);
	struct xfs_inode	*ip = XFS_I(inode);
	ssize_t			ret = 0;
	int			iolock = XFS_IOLOCK_EXCL;
	int			iolock = XFS_IOLOCK_EXCL;
	struct iov_iter		data;
	ssize_t			ret, error = 0;
	size_t			count;
	loff_t			pos;


	xfs_rw_ilock(ip, iolock);
	xfs_rw_ilock(ip, iolock);
	ret = xfs_file_aio_write_checks(iocb, from, &iolock);
	ret = xfs_file_aio_write_checks(iocb, from, &iolock);
	if (ret)
	if (ret)
		goto out;
		goto out;


	/*
	pos = iocb->ki_pos;
	 * Yes, even DAX files can have page cache attached to them:  A zeroed
	count = iov_iter_count(from);
	 * page is inserted into the pagecache when we have to serve a write
	 * fault on a hole.  It should never be dirtied and can simply be
	 * dropped from the pagecache once we get real data for the page.
	 *
	 * XXX: This is racy against mmap, and there's nothing we can do about
	 * it. dax_do_io() should really do this invalidation internally as
	 * it will know if we've allocated over a holei for this specific IO and
	 * if so it needs to update the mapping tree and invalidate existing
	 * PTEs over the newly allocated range. Remove this invalidation when
	 * dax_do_io() is fixed up.
	 */
	if (mapping->nrpages) {
		loff_t end = iocb->ki_pos + iov_iter_count(from) - 1;

		ret = invalidate_inode_pages2_range(mapping,
						    iocb->ki_pos >> PAGE_SHIFT,
						    end >> PAGE_SHIFT);
		WARN_ON_ONCE(ret);
	}


	trace_xfs_file_dax_write(ip, iov_iter_count(from), iocb->ki_pos);
	trace_xfs_file_dax_write(ip, count, pos);


	data = *from;
	ret = iomap_dax_rw(iocb, from, &xfs_iomap_ops);
	ret = dax_do_io(iocb, inode, &data, xfs_get_blocks_direct,
	if (ret > 0 && iocb->ki_pos > i_size_read(inode)) {
			xfs_end_io_direct_write, 0);
		i_size_write(inode, iocb->ki_pos);
	if (ret > 0) {
		error = xfs_setfilesize(ip, pos, ret);
		iocb->ki_pos += ret;
		iov_iter_advance(from, ret);
	}
	}

out:
out:
	xfs_rw_iunlock(ip, iolock);
	xfs_rw_iunlock(ip, iolock);
	return ret;
	return error ? error : ret;
}
}


STATIC ssize_t
STATIC ssize_t
@@ -1495,7 +1468,7 @@ xfs_filemap_page_mkwrite(
	xfs_ilock(XFS_I(inode), XFS_MMAPLOCK_SHARED);
	xfs_ilock(XFS_I(inode), XFS_MMAPLOCK_SHARED);


	if (IS_DAX(inode)) {
	if (IS_DAX(inode)) {
		ret = dax_mkwrite(vma, vmf, xfs_get_blocks_dax_fault);
		ret = iomap_dax_fault(vma, vmf, &xfs_iomap_ops);
	} else {
	} else {
		ret = iomap_page_mkwrite(vma, vmf, &xfs_iomap_ops);
		ret = iomap_page_mkwrite(vma, vmf, &xfs_iomap_ops);
		ret = block_page_mkwrite_return(ret);
		ret = block_page_mkwrite_return(ret);
@@ -1529,7 +1502,7 @@ xfs_filemap_fault(
		 * changes to xfs_get_blocks_direct() to map unwritten extent
		 * changes to xfs_get_blocks_direct() to map unwritten extent
		 * ioend for conversion on read-only mappings.
		 * ioend for conversion on read-only mappings.
		 */
		 */
		ret = dax_fault(vma, vmf, xfs_get_blocks_dax_fault);
		ret = iomap_dax_fault(vma, vmf, &xfs_iomap_ops);
	} else
	} else
		ret = filemap_fault(vma, vmf);
		ret = filemap_fault(vma, vmf);
	xfs_iunlock(XFS_I(inode), XFS_MMAPLOCK_SHARED);
	xfs_iunlock(XFS_I(inode), XFS_MMAPLOCK_SHARED);
+7 −4
Original line number Original line Diff line number Diff line
@@ -934,11 +934,13 @@ xfs_iomap_write_unwritten(
	return error;
	return error;
}
}


static inline bool imap_needs_alloc(struct xfs_bmbt_irec *imap, int nimaps)
static inline bool imap_needs_alloc(struct inode *inode,
		struct xfs_bmbt_irec *imap, int nimaps)
{
{
	return !nimaps ||
	return !nimaps ||
		imap->br_startblock == HOLESTARTBLOCK ||
		imap->br_startblock == HOLESTARTBLOCK ||
		imap->br_startblock == DELAYSTARTBLOCK;
		imap->br_startblock == DELAYSTARTBLOCK ||
		(IS_DAX(inode) && ISUNWRITTEN(imap));
}
}


static int
static int
@@ -959,7 +961,8 @@ xfs_file_iomap_begin(
	if (XFS_FORCED_SHUTDOWN(mp))
	if (XFS_FORCED_SHUTDOWN(mp))
		return -EIO;
		return -EIO;


	if ((flags & IOMAP_WRITE) && !xfs_get_extsz_hint(ip)) {
	if ((flags & IOMAP_WRITE) &&
	    !IS_DAX(inode) && !xfs_get_extsz_hint(ip)) {
		return xfs_file_iomap_begin_delay(inode, offset, length, flags,
		return xfs_file_iomap_begin_delay(inode, offset, length, flags,
				iomap);
				iomap);
	}
	}
@@ -979,7 +982,7 @@ xfs_file_iomap_begin(
		return error;
		return error;
	}
	}


	if ((flags & IOMAP_WRITE) && imap_needs_alloc(&imap, nimaps)) {
	if ((flags & IOMAP_WRITE) && imap_needs_alloc(inode, &imap, nimaps)) {
		/*
		/*
		 * We cap the maximum length we map here to MAX_WRITEBACK_PAGES
		 * We cap the maximum length we map here to MAX_WRITEBACK_PAGES
		 * pages to keep the chunks of work done where somewhat symmetric
		 * pages to keep the chunks of work done where somewhat symmetric