Skip to content

Commit

Permalink
fs: Add initial atomic write support info to statx
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Prasad Singamsetty authored and Jens Axboe committed Jun 20, 2024
1 parent c34fc6f commit 0f9ca80
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 2 deletions.
34 changes: 34 additions & 0 deletions fs/stat.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,37 @@ void generic_fill_statx_attr(struct inode *inode, struct kstat *stat)
}
EXPORT_SYMBOL(generic_fill_statx_attr);

/**
* generic_fill_statx_atomic_writes - Fill in atomic writes statx attributes
* @stat: Where to fill in the attribute flags
* @unit_min: Minimum supported atomic write length in bytes
* @unit_max: Maximum supported atomic write length in bytes
*
* Fill in the STATX{_ATTR}_WRITE_ATOMIC flags in the kstat structure from
* atomic write unit_min and unit_max values.
*/
void generic_fill_statx_atomic_writes(struct kstat *stat,
unsigned int unit_min,
unsigned int unit_max)
{
/* Confirm that the request type is known */
stat->result_mask |= STATX_WRITE_ATOMIC;

/* Confirm that the file attribute type is known */
stat->attributes_mask |= STATX_ATTR_WRITE_ATOMIC;

if (unit_min) {
stat->atomic_write_unit_min = unit_min;
stat->atomic_write_unit_max = unit_max;
/* Initially only allow 1x segment */
stat->atomic_write_segments_max = 1;

/* Confirm atomic writes are actually supported */
stat->attributes |= STATX_ATTR_WRITE_ATOMIC;
}
}
EXPORT_SYMBOL_GPL(generic_fill_statx_atomic_writes);

/**
* vfs_getattr_nosec - getattr without security checks
* @path: file to get attributes from
Expand Down Expand Up @@ -659,6 +690,9 @@ cp_statx(const struct kstat *stat, struct statx __user *buffer)
tmp.stx_dio_mem_align = stat->dio_mem_align;
tmp.stx_dio_offset_align = stat->dio_offset_align;
tmp.stx_subvol = stat->subvol;
tmp.stx_atomic_write_unit_min = stat->atomic_write_unit_min;
tmp.stx_atomic_write_unit_max = stat->atomic_write_unit_max;
tmp.stx_atomic_write_segments_max = stat->atomic_write_segments_max;

return copy_to_user(buffer, &tmp, sizeof(tmp)) ? -EFAULT : 0;
}
Expand Down
3 changes: 3 additions & 0 deletions include/linux/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -3235,6 +3235,9 @@ extern const struct inode_operations page_symlink_inode_operations;
extern void kfree_link(void *);
void generic_fillattr(struct mnt_idmap *, u32, struct inode *, struct kstat *);
void generic_fill_statx_attr(struct inode *inode, struct kstat *stat);
void generic_fill_statx_atomic_writes(struct kstat *stat,
unsigned int unit_min,
unsigned int unit_max);
extern int vfs_getattr_nosec(const struct path *, struct kstat *, u32, unsigned int);
extern int vfs_getattr(const struct path *, struct kstat *, u32, unsigned int);
void __inode_add_bytes(struct inode *inode, loff_t bytes);
Expand Down
3 changes: 3 additions & 0 deletions include/linux/stat.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ struct kstat {
u32 dio_offset_align;
u64 change_cookie;
u64 subvol;
u32 atomic_write_unit_min;
u32 atomic_write_unit_max;
u32 atomic_write_segments_max;
};

/* These definitions are internal to the kernel for now. Mainly used by nfsd. */
Expand Down
12 changes: 10 additions & 2 deletions include/uapi/linux/stat.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,15 @@ struct statx {
__u64 stx_mnt_id;
__u32 stx_dio_mem_align; /* Memory buffer alignment for direct I/O */
__u32 stx_dio_offset_align; /* File offset alignment for direct I/O */
__u64 stx_subvol; /* Subvolume identifier */
/* 0xa0 */
__u64 __spare3[11]; /* Spare space for future expansion */
__u64 stx_subvol; /* Subvolume identifier */
__u32 stx_atomic_write_unit_min; /* Min atomic write unit in bytes */
__u32 stx_atomic_write_unit_max; /* Max atomic write unit in bytes */
/* 0xb0 */
__u32 stx_atomic_write_segments_max; /* Max atomic write segment count */
__u32 __spare1[1];
/* 0xb8 */
__u64 __spare3[9]; /* Spare space for future expansion */
/* 0x100 */
};

Expand Down Expand Up @@ -157,6 +163,7 @@ struct statx {
#define STATX_DIOALIGN 0x00002000U /* Want/got direct I/O alignment info */
#define STATX_MNT_ID_UNIQUE 0x00004000U /* Want/got extended stx_mount_id */
#define STATX_SUBVOL 0x00008000U /* Want/got stx_subvol */
#define STATX_WRITE_ATOMIC 0x00010000U /* Want/got atomic_write_* fields */

#define STATX__RESERVED 0x80000000U /* Reserved for future struct statx expansion */

Expand Down Expand Up @@ -192,6 +199,7 @@ struct statx {
#define STATX_ATTR_MOUNT_ROOT 0x00002000 /* Root of a mount */
#define STATX_ATTR_VERITY 0x00100000 /* [I] Verity protected file */
#define STATX_ATTR_DAX 0x00200000 /* File is currently in DAX state */
#define STATX_ATTR_WRITE_ATOMIC 0x00400000 /* File supports atomic write operations */


#endif /* _UAPI_LINUX_STAT_H */

0 comments on commit 0f9ca80

Please sign in to comment.