Currently the size of atomic write allowed is fixed at the blocksize. To start to lift this restriction, partly refactor xfs_report_atomic_write() to into helpers - xfs_get_atomic_write_{min, max}_attr() - and use those helpers to find the per-inode atomic write limits and check according to that. Reviewed-by: Darrick J. Wong <djwong@xxxxxxxxxx> Signed-off-by: John Garry <john.g.garry@xxxxxxxxxx> --- fs/xfs/xfs_file.c | 12 +++++------- fs/xfs/xfs_iops.c | 28 +++++++++++++++++++++++----- fs/xfs/xfs_iops.h | 2 ++ 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index fe8cf9d96eb0..7a56ddb86fd2 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -1032,14 +1032,12 @@ xfs_file_write_iter( return xfs_file_dax_write(iocb, from); if (iocb->ki_flags & IOCB_ATOMIC) { - /* - * Currently only atomic writing of a single FS block is - * supported. It would be possible to atomic write smaller than - * a FS block, but there is no requirement to support this. - * Note that iomap also does not support this yet. - */ - if (ocount != ip->i_mount->m_sb.sb_blocksize) + if (ocount < xfs_get_atomic_write_min_attr(ip)) return -EINVAL; + + if (ocount > xfs_get_atomic_write_max_attr(ip)) + return -EINVAL; + ret = generic_atomic_write_valid(iocb, from); if (ret) return ret; diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 444193f543ef..64b1f8c73824 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -601,16 +601,34 @@ xfs_report_dioalign( stat->dio_offset_align = stat->dio_read_offset_align; } +unsigned int +xfs_get_atomic_write_min_attr( + struct xfs_inode *ip) +{ + if (!xfs_inode_can_atomicwrite(ip)) + return 0; + + return ip->i_mount->m_sb.sb_blocksize; +} + +unsigned int +xfs_get_atomic_write_max_attr( + struct xfs_inode *ip) +{ + if (!xfs_inode_can_atomicwrite(ip)) + return 0; + + return ip->i_mount->m_sb.sb_blocksize; +} + static void xfs_report_atomic_write( struct xfs_inode *ip, struct kstat *stat) { - unsigned int unit_min = 0, unit_max = 0; - - if (xfs_inode_can_atomicwrite(ip)) - unit_min = unit_max = ip->i_mount->m_sb.sb_blocksize; - generic_fill_statx_atomic_writes(stat, unit_min, unit_max); + generic_fill_statx_atomic_writes(stat, + xfs_get_atomic_write_min_attr(ip), + xfs_get_atomic_write_max_attr(ip)); } STATIC int diff --git a/fs/xfs/xfs_iops.h b/fs/xfs/xfs_iops.h index 3c1a2605ffd2..3ef3bb632ad8 100644 --- a/fs/xfs/xfs_iops.h +++ b/fs/xfs/xfs_iops.h @@ -19,5 +19,7 @@ int xfs_inode_init_security(struct inode *inode, struct inode *dir, extern void xfs_setup_inode(struct xfs_inode *ip); extern void xfs_setup_iops(struct xfs_inode *ip); extern void xfs_diflags_to_iflags(struct xfs_inode *ip, bool init); +unsigned int xfs_get_atomic_write_min_attr(struct xfs_inode *ip); +unsigned int xfs_get_atomic_write_max_attr(struct xfs_inode *ip); #endif /* __XFS_IOPS_H__ */ -- 2.31.1