forked from mirrors/linux
		
	xfs: support CoW in fsdax mode
In fsdax mode, WRITE and ZERO on a shared extent need CoW performed. After that, new allocated extents needs to be remapped to the file. So, add a CoW identification in ->iomap_begin(), and implement ->iomap_end() to do the remapping work. [akpm@linux-foundation.org: make xfs_dax_fault() static] Link: https://lkml.kernel.org/r/20220603053738.1218681-14-ruansy.fnst@fujitsu.com Signed-off-by: Shiyang Ruan <ruansy.fnst@fujitsu.com> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Christoph Hellwig <hch@lst.de> Cc: Dan Williams <dan.j.wiliams@intel.com> Cc: Dan Williams <dan.j.williams@intel.com> Cc: Dave Chinner <david@fromorbit.com> Cc: Goldwyn Rodrigues <rgoldwyn@suse.com> Cc: Goldwyn Rodrigues <rgoldwyn@suse.de> Cc: Jane Chu <jane.chu@oracle.com> Cc: Matthew Wilcox <willy@infradead.org> Cc: Miaohe Lin <linmiaohe@huawei.com> Cc: Naoya Horiguchi <naoya.horiguchi@nec.com> Cc: Ritesh Harjani <riteshh@linux.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									6f7db3894a
								
							
						
					
					
						commit
						ea6c49b784
					
				
					 3 changed files with 58 additions and 6 deletions
				
			
		| 
						 | 
					@ -25,6 +25,7 @@
 | 
				
			||||||
#include "xfs_iomap.h"
 | 
					#include "xfs_iomap.h"
 | 
				
			||||||
#include "xfs_reflink.h"
 | 
					#include "xfs_reflink.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/dax.h>
 | 
				
			||||||
#include <linux/falloc.h>
 | 
					#include <linux/falloc.h>
 | 
				
			||||||
#include <linux/backing-dev.h>
 | 
					#include <linux/backing-dev.h>
 | 
				
			||||||
#include <linux/mman.h>
 | 
					#include <linux/mman.h>
 | 
				
			||||||
| 
						 | 
					@ -669,7 +670,7 @@ xfs_file_dax_write(
 | 
				
			||||||
	pos = iocb->ki_pos;
 | 
						pos = iocb->ki_pos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	trace_xfs_file_dax_write(iocb, from);
 | 
						trace_xfs_file_dax_write(iocb, from);
 | 
				
			||||||
	ret = dax_iomap_rw(iocb, from, &xfs_direct_write_iomap_ops);
 | 
						ret = dax_iomap_rw(iocb, from, &xfs_dax_write_iomap_ops);
 | 
				
			||||||
	if (ret > 0 && iocb->ki_pos > i_size_read(inode)) {
 | 
						if (ret > 0 && iocb->ki_pos > i_size_read(inode)) {
 | 
				
			||||||
		i_size_write(inode, iocb->ki_pos);
 | 
							i_size_write(inode, iocb->ki_pos);
 | 
				
			||||||
		error = xfs_setfilesize(ip, pos, ret);
 | 
							error = xfs_setfilesize(ip, pos, ret);
 | 
				
			||||||
| 
						 | 
					@ -1254,6 +1255,31 @@ xfs_file_llseek(
 | 
				
			||||||
	return vfs_setpos(file, offset, inode->i_sb->s_maxbytes);
 | 
						return vfs_setpos(file, offset, inode->i_sb->s_maxbytes);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_FS_DAX
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					xfs_dax_fault(
 | 
				
			||||||
 | 
						struct vm_fault		*vmf,
 | 
				
			||||||
 | 
						enum page_entry_size	pe_size,
 | 
				
			||||||
 | 
						bool			write_fault,
 | 
				
			||||||
 | 
						pfn_t			*pfn)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return dax_iomap_fault(vmf, pe_size, pfn, NULL,
 | 
				
			||||||
 | 
								(write_fault && !vmf->cow_page) ?
 | 
				
			||||||
 | 
									&xfs_dax_write_iomap_ops :
 | 
				
			||||||
 | 
									&xfs_read_iomap_ops);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					xfs_dax_fault(
 | 
				
			||||||
 | 
						struct vm_fault		*vmf,
 | 
				
			||||||
 | 
						enum page_entry_size	pe_size,
 | 
				
			||||||
 | 
						bool			write_fault,
 | 
				
			||||||
 | 
						pfn_t			*pfn)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Locking for serialisation of IO during page faults. This results in a lock
 | 
					 * Locking for serialisation of IO during page faults. This results in a lock
 | 
				
			||||||
 * ordering of:
 | 
					 * ordering of:
 | 
				
			||||||
| 
						 | 
					@ -1285,10 +1311,7 @@ __xfs_filemap_fault(
 | 
				
			||||||
		pfn_t pfn;
 | 
							pfn_t pfn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		xfs_ilock(XFS_I(inode), XFS_MMAPLOCK_SHARED);
 | 
							xfs_ilock(XFS_I(inode), XFS_MMAPLOCK_SHARED);
 | 
				
			||||||
		ret = dax_iomap_fault(vmf, pe_size, &pfn, NULL,
 | 
							ret = xfs_dax_fault(vmf, pe_size, write_fault, &pfn);
 | 
				
			||||||
				(write_fault && !vmf->cow_page) ?
 | 
					 | 
				
			||||||
				 &xfs_direct_write_iomap_ops :
 | 
					 | 
				
			||||||
				 &xfs_read_iomap_ops);
 | 
					 | 
				
			||||||
		if (ret & VM_FAULT_NEEDDSYNC)
 | 
							if (ret & VM_FAULT_NEEDDSYNC)
 | 
				
			||||||
			ret = dax_finish_sync_fault(vmf, pe_size, pfn);
 | 
								ret = dax_finish_sync_fault(vmf, pe_size, pfn);
 | 
				
			||||||
		xfs_iunlock(XFS_I(inode), XFS_MMAPLOCK_SHARED);
 | 
							xfs_iunlock(XFS_I(inode), XFS_MMAPLOCK_SHARED);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -773,7 +773,8 @@ xfs_direct_write_iomap_begin(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* may drop and re-acquire the ilock */
 | 
							/* may drop and re-acquire the ilock */
 | 
				
			||||||
		error = xfs_reflink_allocate_cow(ip, &imap, &cmap, &shared,
 | 
							error = xfs_reflink_allocate_cow(ip, &imap, &cmap, &shared,
 | 
				
			||||||
				&lockmode, flags & IOMAP_DIRECT);
 | 
									&lockmode,
 | 
				
			||||||
 | 
									(flags & IOMAP_DIRECT) || IS_DAX(inode));
 | 
				
			||||||
		if (error)
 | 
							if (error)
 | 
				
			||||||
			goto out_unlock;
 | 
								goto out_unlock;
 | 
				
			||||||
		if (shared)
 | 
							if (shared)
 | 
				
			||||||
| 
						 | 
					@ -867,6 +868,33 @@ const struct iomap_ops xfs_direct_write_iomap_ops = {
 | 
				
			||||||
	.iomap_begin		= xfs_direct_write_iomap_begin,
 | 
						.iomap_begin		= xfs_direct_write_iomap_begin,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					xfs_dax_write_iomap_end(
 | 
				
			||||||
 | 
						struct inode		*inode,
 | 
				
			||||||
 | 
						loff_t			pos,
 | 
				
			||||||
 | 
						loff_t			length,
 | 
				
			||||||
 | 
						ssize_t			written,
 | 
				
			||||||
 | 
						unsigned		flags,
 | 
				
			||||||
 | 
						struct iomap		*iomap)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct xfs_inode	*ip = XFS_I(inode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!xfs_is_cow_inode(ip))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!written) {
 | 
				
			||||||
 | 
							xfs_reflink_cancel_cow_range(ip, pos, length, true);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return xfs_reflink_end_cow(ip, pos, written);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct iomap_ops xfs_dax_write_iomap_ops = {
 | 
				
			||||||
 | 
						.iomap_begin	= xfs_direct_write_iomap_begin,
 | 
				
			||||||
 | 
						.iomap_end	= xfs_dax_write_iomap_end,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
xfs_buffered_write_iomap_begin(
 | 
					xfs_buffered_write_iomap_begin(
 | 
				
			||||||
	struct inode		*inode,
 | 
						struct inode		*inode,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,5 +51,6 @@ extern const struct iomap_ops xfs_direct_write_iomap_ops;
 | 
				
			||||||
extern const struct iomap_ops xfs_read_iomap_ops;
 | 
					extern const struct iomap_ops xfs_read_iomap_ops;
 | 
				
			||||||
extern const struct iomap_ops xfs_seek_iomap_ops;
 | 
					extern const struct iomap_ops xfs_seek_iomap_ops;
 | 
				
			||||||
extern const struct iomap_ops xfs_xattr_iomap_ops;
 | 
					extern const struct iomap_ops xfs_xattr_iomap_ops;
 | 
				
			||||||
 | 
					extern const struct iomap_ops xfs_dax_write_iomap_ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* __XFS_IOMAP_H__*/
 | 
					#endif /* __XFS_IOMAP_H__*/
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue