Support providing info on atomic write unit min and max for an inode. For simplicity, currently we limit the min at the FS block size, but a lower limit could be supported in future. The atomic write unit min and max is limited by the guaranteed extent alignment for the inode. Signed-off-by: John Garry <john.g.garry@xxxxxxxxxx> --- fs/xfs/xfs_iops.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_iops.h | 4 ++++ 2 files changed, 49 insertions(+) diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index a0d77f5f512e..0890d2f70f4d 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -546,6 +546,44 @@ xfs_stat_blksize( return PAGE_SIZE; } +void xfs_get_atomic_write_attr( + struct xfs_inode *ip, + unsigned int *unit_min, + unsigned int *unit_max) +{ + xfs_extlen_t extsz = xfs_get_extsz(ip); + struct xfs_buftarg *target = xfs_inode_buftarg(ip); + struct block_device *bdev = target->bt_bdev; + unsigned int awu_min, awu_max, align; + struct request_queue *q = bdev->bd_queue; + struct xfs_mount *mp = ip->i_mount; + + /* + * Convert to multiples of the BLOCKSIZE (as we support a minimum + * atomic write unit of BLOCKSIZE). + */ + awu_min = queue_atomic_write_unit_min_bytes(q); + awu_max = queue_atomic_write_unit_max_bytes(q); + + awu_min &= ~mp->m_blockmask; + awu_max &= ~mp->m_blockmask; + + align = XFS_FSB_TO_B(mp, extsz); + + if (!awu_max || !xfs_inode_atomicwrites(ip) || !align || + !is_power_of_2(align)) { + *unit_min = 0; + *unit_max = 0; + } else { + if (awu_min) + *unit_min = min(awu_min, align); + else + *unit_min = mp->m_sb.sb_blocksize; + + *unit_max = min(awu_max, align); + } +} + STATIC int xfs_vn_getattr( struct mnt_idmap *idmap, @@ -619,6 +657,13 @@ xfs_vn_getattr( stat->dio_mem_align = bdev_dma_alignment(bdev) + 1; stat->dio_offset_align = bdev_logical_block_size(bdev); } + if (request_mask & STATX_WRITE_ATOMIC) { + unsigned int unit_min, unit_max; + + xfs_get_atomic_write_attr(ip, &unit_min, &unit_max); + generic_fill_statx_atomic_writes(stat, + unit_min, unit_max); + } fallthrough; default: stat->blksize = xfs_stat_blksize(ip); diff --git a/fs/xfs/xfs_iops.h b/fs/xfs/xfs_iops.h index 7f84a0843b24..76dd4c3687aa 100644 --- a/fs/xfs/xfs_iops.h +++ b/fs/xfs/xfs_iops.h @@ -19,4 +19,8 @@ int xfs_vn_setattr_size(struct mnt_idmap *idmap, int xfs_inode_init_security(struct inode *inode, struct inode *dir, const struct qstr *qstr); +void xfs_get_atomic_write_attr(struct xfs_inode *ip, + unsigned int *unit_min, + unsigned int *unit_max); + #endif /* __XFS_IOPS_H__ */ -- 2.31.1