Commit ea6c49b7 authored by Shiyang Ruan's avatar Shiyang Ruan Committed by akpm

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.comSigned-off-by: default avatarShiyang Ruan <ruansy.fnst@fujitsu.com>
Reviewed-by: default avatarDarrick 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: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 6f7db389
...@@ -25,6 +25,7 @@ ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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 = { ...@@ -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; ...@@ -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__*/
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment