summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2021-09-17 16:28:25 -0700
committerDarrick J. Wong <djwong@kernel.org>2021-09-23 18:20:32 -0700
commit7411eba7d39f53f012f51d6c6304b3901bdcf0fd (patch)
treea32faa0ab9c0ef94469927162224c3992bb0aeb7
parent13fade90ac574fc78f55d0935a95f5fff16f7695 (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.c22
-rw-r--r--fs/xfs/xfs_bmap_util.h2
-rw-r--r--fs/xfs/xfs_file.c25
-rw-r--r--fs/xfs/xfs_trace.h1
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),