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. Signed-off-by: Ojaswin Mujoo <ojaswin@xxxxxxxxxxxxx> --- fs/ext4/inode.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index d185ec54ffa3..c8f974d0f113 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -5621,6 +5621,7 @@ int ext4_getattr(struct mnt_idmap *idmap, const struct path *path, struct ext4_inode *raw_inode; struct ext4_inode_info *ei = EXT4_I(inode); unsigned int flags; + struct block_device *bdev = inode->i_sb->s_bdev; if ((request_mask & STATX_BTIME) && EXT4_FITS_IN_INODE(raw_inode, ei, i_crtime)) { @@ -5639,8 +5640,6 @@ int ext4_getattr(struct mnt_idmap *idmap, const struct path *path, stat->result_mask |= STATX_DIOALIGN; if (dio_align == 1) { - struct block_device *bdev = inode->i_sb->s_bdev; - /* iomap defaults */ stat->dio_mem_align = bdev_dma_alignment(bdev) + 1; stat->dio_offset_align = bdev_logical_block_size(bdev); @@ -5650,6 +5649,41 @@ int ext4_getattr(struct mnt_idmap *idmap, const struct path *path, } } + if ((request_mask & STATX_WRITE_ATOMIC)) { + unsigned int awumin, awumax; + unsigned int blocksize = 1 << inode->i_blkbits; + + awumin = queue_atomic_write_unit_min_bytes(bdev->bd_queue); + awumax = queue_atomic_write_unit_max_bytes(bdev->bd_queue); + + if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) || + EXT4_SB(inode->i_sb)->s_cluster_ratio > 1) { + /* + * Currently not supported for non extent files or + * with bigalloc + */ + stat->atomic_write_unit_min = 0; + stat->atomic_write_unit_max = 0; + } else if (awumin && awumax) { + /* + * For now we support atomic writes which are + * at least block size bytes. If that exceeds the + * max atomic unit, then don't advertise support + */ + stat->atomic_write_unit_min = max(awumin, blocksize); + + if (awumax < stat->atomic_write_unit_min) { + stat->atomic_write_unit_min = 0; + stat->atomic_write_unit_max = 0; + } else { + stat->atomic_write_unit_max = awumax; + stat->attributes |= STATX_ATTR_WRITE_ATOMIC; + } + } + stat->attributes_mask |= STATX_ATTR_WRITE_ATOMIC; + stat->result_mask |= STATX_WRITE_ATOMIC; + } + flags = ei->i_flags & EXT4_FL_USER_VISIBLE; if (flags & EXT4_APPEND_FL) stat->attributes |= STATX_ATTR_APPEND; -- 2.39.3