On Wed, Jan 24, 2024 at 02:26:43PM +0000, John Garry wrote: > 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( static void? > + struct xfs_inode *ip, > + unsigned int *unit_min, > + unsigned int *unit_max) Weird indenting here. > +{ > + 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; Why do you round /down/ the awu_min value here? > + awu_max &= ~mp->m_blockmask; Actually -- since the atomic write units have to be powers of 2, why is rounding needed here at all? > + > + align = XFS_FSB_TO_B(mp, extsz); > + > + if (!awu_max || !xfs_inode_atomicwrites(ip) || !align || > + !is_power_of_2(align)) { ...and if you take my suggestion to make a common helper to validate the atomic write unit parameters, this can collapse into: alloc_unit_bytes = xfs_inode_alloc_unitsize(ip); if (!xfs_inode_has_atomicwrites(ip) || !bdev_validate_atomic_write(bdev, alloc_unit_bytes)) { /* not supported, return zeroes */ *unit_min = 0; *unit_max = 0; return; } *unit_min = max(alloc_unit_bytes, awu_min); *unit_max = min(alloc_unit_bytes, awu_max); --D > + *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 > >