diff options
author | Darrick J. Wong <djwong@kernel.org> | 2021-09-17 16:28:25 -0700 |
---|---|---|
committer | Darrick J. Wong <djwong@kernel.org> | 2021-09-23 18:20:32 -0700 |
commit | 7411eba7d39f53f012f51d6c6304b3901bdcf0fd (patch) | |
tree | a32faa0ab9c0ef94469927162224c3992bb0aeb7 | |
parent | 13fade90ac574fc78f55d0935a95f5fff16f7695 (diff) |
xfs: implement FALLOC_FL_ZEROINIT_RANGE
Implement this new fallocate mode so that persistent memory users can,
upon receipt of a pmem poison notification, cause the pmem to be
reinitialized to a known value (zero) and clear any hardware poison
state that might be lurking.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
-rw-r--r-- | fs/xfs/xfs_bmap_util.c | 22 | ||||
-rw-r--r-- | fs/xfs/xfs_bmap_util.h | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_file.c | 25 | ||||
-rw-r--r-- | fs/xfs/xfs_trace.h | 1 |
4 files changed, 48 insertions, 2 deletions
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 73a36b7be3bd..e2e7e6a488a1 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -957,6 +957,28 @@ xfs_flush_unmap_range( } int +xfs_file_zeroinit_space( + struct xfs_inode *ip, + xfs_off_t offset, + xfs_off_t len) +{ + struct inode *inode = VFS_I(ip); + int error; + + trace_xfs_zeroinit_file_space(ip, offset, len); + + if (IS_DAX(inode)) + error = dax_zeroinit_range(inode, offset, len, + &xfs_read_iomap_ops); + else + error = iomap_zeroout_range(inode, offset, len, + &xfs_buffered_write_iomap_ops); + if (error == -ECANCELED) + return -EOPNOTSUPP; + return error; +} + +int xfs_free_file_space( struct xfs_inode *ip, xfs_off_t offset, diff --git a/fs/xfs/xfs_bmap_util.h b/fs/xfs/xfs_bmap_util.h index 9f993168b55b..7bb425d0876c 100644 --- a/fs/xfs/xfs_bmap_util.h +++ b/fs/xfs/xfs_bmap_util.h @@ -61,6 +61,8 @@ int xfs_collapse_file_space(struct xfs_inode *, xfs_off_t offset, xfs_off_t len); int xfs_insert_file_space(struct xfs_inode *, xfs_off_t offset, xfs_off_t len); +int xfs_file_zeroinit_space(struct xfs_inode *ip, xfs_off_t offset, + xfs_off_t length); /* EOF block manipulation functions */ bool xfs_can_free_eofblocks(struct xfs_inode *ip, bool force); diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 7aa943edfc02..c6ba37703f0b 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -899,7 +899,8 @@ xfs_break_layouts( #define XFS_FALLOC_FL_SUPPORTED \ (FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE | \ FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE | \ - FALLOC_FL_INSERT_RANGE | FALLOC_FL_UNSHARE_RANGE) + FALLOC_FL_INSERT_RANGE | FALLOC_FL_UNSHARE_RANGE | \ + FALLOC_FL_ZEROINIT_DATA) STATIC long xfs_file_fallocate( @@ -1005,6 +1006,8 @@ xfs_file_fallocate( } do_file_insert = true; } else { + unsigned int bmapi_flags = XFS_BMAPI_PREALLOC; + flags |= XFS_PREALLOC_SET; if (!(mode & FALLOC_FL_KEEP_SIZE) && @@ -1015,6 +1018,24 @@ xfs_file_fallocate( goto out_unlock; } + if (mode & FALLOC_FL_ZEROINIT_DATA) { + if (xfs_is_always_cow_inode(ip)) { + error = -EOPNOTSUPP; + goto out_unlock; + } + + bmapi_flags = XFS_BMAPI_ZERO; + + if (mode & FALLOC_FL_ZERO_RANGE) { + error = xfs_file_zeroinit_space(ip, offset, + len); + if (error) + goto out_unlock; + + mode &= ~FALLOC_FL_ZERO_RANGE; + } + } + if (mode & FALLOC_FL_ZERO_RANGE) { /* * Punch a hole and prealloc the range. We use a hole @@ -1053,7 +1074,7 @@ xfs_file_fallocate( if (!xfs_is_always_cow_inode(ip)) { error = xfs_alloc_file_space(ip, offset, len, - XFS_BMAPI_PREALLOC); + bmapi_flags); if (error) goto out_unlock; } diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 4a8076ef8cb4..eccad0a5c40f 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -1534,6 +1534,7 @@ DEFINE_SIMPLE_IO_EVENT(xfs_zero_eof); DEFINE_SIMPLE_IO_EVENT(xfs_end_io_direct_write); DEFINE_SIMPLE_IO_EVENT(xfs_end_io_direct_write_unwritten); DEFINE_SIMPLE_IO_EVENT(xfs_end_io_direct_write_append); +DEFINE_SIMPLE_IO_EVENT(xfs_zeroinit_file_space); DECLARE_EVENT_CLASS(xfs_itrunc_class, TP_PROTO(struct xfs_inode *ip, xfs_fsize_t new_size), |