From: John Garry john.g.garry@oracle.com
maillist inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9VTE3 CVE: NA
Reference: https://lore.kernel.org/all/20240326133813.3224593-1-john.g.garry@oracle.com...
--------------------------------
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. This is required by iomap DIO.
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@oracle.com Signed-off-by: Long Li leo.lilong@huawei.com --- fs/xfs/xfs_iops.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+)
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index a527a544a684..8446b145130c 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -507,6 +507,37 @@ xfs_stat_blksize( return PAGE_SIZE; }
+static 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; + struct request_queue *q = bdev_get_queue(bdev); + struct xfs_mount *mp = ip->i_mount; + struct xfs_sb *sbp = &mp->m_sb; + unsigned int awu_min, awu_max; + unsigned int extsz_bytes = XFS_FSB_TO_B(mp, extsz); + + awu_min = queue_atomic_write_unit_min_bytes(q); + awu_max = queue_atomic_write_unit_max_bytes(q); + + if (sbp->sb_blocksize > awu_max || awu_min > sbp->sb_blocksize || + !xfs_inode_atomicwrites(ip)) { + *unit_min = 0; + *unit_max = 0; + return; + } + + /* Floor at FS block size */ + *unit_min = max(sbp->sb_blocksize, awu_min); + + *unit_max = min(extsz_bytes, awu_max); +} + STATIC int xfs_vn_getattr( const struct path *path, @@ -564,6 +595,15 @@ xfs_vn_getattr( stat->blksize = BLKDEV_IOSIZE; stat->rdev = inode->i_rdev; break; + case S_IFREG: + 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); stat->rdev = 0;