Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fs: Add initial atomic write support info to statx

Extend statx system call to return additional info for atomic write support
support for a file.

Helper function generic_fill_statx_atomic_writes() can be used by FSes to
fill in the relevant statx fields. For now atomic_write_segments_max will
always be 1, otherwise some rules would need to be imposed on iovec length
and alignment, which we don't want now.

Signed-off-by: Prasad Singamsetty <prasad.singamsetty@oracle.com>
jpg: relocate bdev support to another patch
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: John Garry <john.g.garry@oracle.com>
Acked-by: Darrick J. Wong <djwong@kernel.org>
Link: https://lore.kernel.org/r/20240620125359.2684798-5-john.g.garry@oracle.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Prasad Singamsetty and committed by
Jens Axboe
0f9ca80f c34fc6f2

+50 -2
+34
fs/stat.c
··· 90 90 EXPORT_SYMBOL(generic_fill_statx_attr); 91 91 92 92 /** 93 + * generic_fill_statx_atomic_writes - Fill in atomic writes statx attributes 94 + * @stat: Where to fill in the attribute flags 95 + * @unit_min: Minimum supported atomic write length in bytes 96 + * @unit_max: Maximum supported atomic write length in bytes 97 + * 98 + * Fill in the STATX{_ATTR}_WRITE_ATOMIC flags in the kstat structure from 99 + * atomic write unit_min and unit_max values. 100 + */ 101 + void generic_fill_statx_atomic_writes(struct kstat *stat, 102 + unsigned int unit_min, 103 + unsigned int unit_max) 104 + { 105 + /* Confirm that the request type is known */ 106 + stat->result_mask |= STATX_WRITE_ATOMIC; 107 + 108 + /* Confirm that the file attribute type is known */ 109 + stat->attributes_mask |= STATX_ATTR_WRITE_ATOMIC; 110 + 111 + if (unit_min) { 112 + stat->atomic_write_unit_min = unit_min; 113 + stat->atomic_write_unit_max = unit_max; 114 + /* Initially only allow 1x segment */ 115 + stat->atomic_write_segments_max = 1; 116 + 117 + /* Confirm atomic writes are actually supported */ 118 + stat->attributes |= STATX_ATTR_WRITE_ATOMIC; 119 + } 120 + } 121 + EXPORT_SYMBOL_GPL(generic_fill_statx_atomic_writes); 122 + 123 + /** 93 124 * vfs_getattr_nosec - getattr without security checks 94 125 * @path: file to get attributes from 95 126 * @stat: structure to return attributes in ··· 690 659 tmp.stx_dio_mem_align = stat->dio_mem_align; 691 660 tmp.stx_dio_offset_align = stat->dio_offset_align; 692 661 tmp.stx_subvol = stat->subvol; 662 + tmp.stx_atomic_write_unit_min = stat->atomic_write_unit_min; 663 + tmp.stx_atomic_write_unit_max = stat->atomic_write_unit_max; 664 + tmp.stx_atomic_write_segments_max = stat->atomic_write_segments_max; 693 665 694 666 return copy_to_user(buffer, &tmp, sizeof(tmp)) ? -EFAULT : 0; 695 667 }
+3
include/linux/fs.h
··· 3235 3235 extern void kfree_link(void *); 3236 3236 void generic_fillattr(struct mnt_idmap *, u32, struct inode *, struct kstat *); 3237 3237 void generic_fill_statx_attr(struct inode *inode, struct kstat *stat); 3238 + void generic_fill_statx_atomic_writes(struct kstat *stat, 3239 + unsigned int unit_min, 3240 + unsigned int unit_max); 3238 3241 extern int vfs_getattr_nosec(const struct path *, struct kstat *, u32, unsigned int); 3239 3242 extern int vfs_getattr(const struct path *, struct kstat *, u32, unsigned int); 3240 3243 void __inode_add_bytes(struct inode *inode, loff_t bytes);
+3
include/linux/stat.h
··· 54 54 u32 dio_offset_align; 55 55 u64 change_cookie; 56 56 u64 subvol; 57 + u32 atomic_write_unit_min; 58 + u32 atomic_write_unit_max; 59 + u32 atomic_write_segments_max; 57 60 }; 58 61 59 62 /* These definitions are internal to the kernel for now. Mainly used by nfsd. */
+10 -2
include/uapi/linux/stat.h
··· 126 126 __u64 stx_mnt_id; 127 127 __u32 stx_dio_mem_align; /* Memory buffer alignment for direct I/O */ 128 128 __u32 stx_dio_offset_align; /* File offset alignment for direct I/O */ 129 - __u64 stx_subvol; /* Subvolume identifier */ 130 129 /* 0xa0 */ 131 - __u64 __spare3[11]; /* Spare space for future expansion */ 130 + __u64 stx_subvol; /* Subvolume identifier */ 131 + __u32 stx_atomic_write_unit_min; /* Min atomic write unit in bytes */ 132 + __u32 stx_atomic_write_unit_max; /* Max atomic write unit in bytes */ 133 + /* 0xb0 */ 134 + __u32 stx_atomic_write_segments_max; /* Max atomic write segment count */ 135 + __u32 __spare1[1]; 136 + /* 0xb8 */ 137 + __u64 __spare3[9]; /* Spare space for future expansion */ 132 138 /* 0x100 */ 133 139 }; 134 140 ··· 163 157 #define STATX_DIOALIGN 0x00002000U /* Want/got direct I/O alignment info */ 164 158 #define STATX_MNT_ID_UNIQUE 0x00004000U /* Want/got extended stx_mount_id */ 165 159 #define STATX_SUBVOL 0x00008000U /* Want/got stx_subvol */ 160 + #define STATX_WRITE_ATOMIC 0x00010000U /* Want/got atomic_write_* fields */ 166 161 167 162 #define STATX__RESERVED 0x80000000U /* Reserved for future struct statx expansion */ 168 163 ··· 199 192 #define STATX_ATTR_MOUNT_ROOT 0x00002000 /* Root of a mount */ 200 193 #define STATX_ATTR_VERITY 0x00100000 /* [I] Verity protected file */ 201 194 #define STATX_ATTR_DAX 0x00200000 /* File is currently in DAX state */ 195 + #define STATX_ATTR_WRITE_ATOMIC 0x00400000 /* File supports atomic write operations */ 202 196 203 197 204 198 #endif /* _UAPI_LINUX_STAT_H */