Skip to content

Commit 5d89432

Browse files
johnpgarryDarrick J. Wong
authored andcommitted
fs: add atomic write unit max opt to statx
XFS will be able to support large atomic writes (atomic write > 1x block) in future. This will be achieved by using different operating methods, depending on the size of the write. Specifically a new method of operation based in FS atomic extent remapping will be supported in addition to the current HW offload-based method. The FS method will generally be appreciably slower performing than the HW-offload method. However the FS method will be typically able to contribute to achieving a larger atomic write unit max limit. XFS will support a hybrid mode, where HW offload method will be used when possible, i.e. HW offload is used when the length of the write is supported, and for other times FS-based atomic writes will be used. As such, there is an atomic write length at which the user may experience appreciably slower performance. Advertise this limit in a new statx field, stx_atomic_write_unit_max_opt. When zero, it means that there is no such performance boundary. Masks STATX{_ATTR}_WRITE_ATOMIC can be used to get this new field. This is ok for older kernels which don't support this new field, as they would report 0 in this field (from zeroing in cp_statx()) already. Furthermore those older kernels don't support large atomic writes - apart from block fops, but there would be consistent performance there for atomic writes in range [unit min, unit max]. Reviewed-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Darrick J. Wong <djwong@kernel.org> Acked-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: John Garry <john.g.garry@oracle.com>
1 parent bfecc40 commit 5d89432

7 files changed

Lines changed: 18 additions & 7 deletions

File tree

block/bdev.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1336,7 +1336,8 @@ void bdev_statx(struct path *path, struct kstat *stat,
13361336

13371337
generic_fill_statx_atomic_writes(stat,
13381338
queue_atomic_write_unit_min_bytes(bd_queue),
1339-
queue_atomic_write_unit_max_bytes(bd_queue));
1339+
queue_atomic_write_unit_max_bytes(bd_queue),
1340+
0);
13401341
}
13411342

13421343
stat->blksize = bdev_io_min(bdev);

fs/ext4/inode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5692,7 +5692,7 @@ int ext4_getattr(struct mnt_idmap *idmap, const struct path *path,
56925692
awu_max = sbi->s_awu_max;
56935693
}
56945694

5695-
generic_fill_statx_atomic_writes(stat, awu_min, awu_max);
5695+
generic_fill_statx_atomic_writes(stat, awu_min, awu_max, 0);
56965696
}
56975697

56985698
flags = ei->i_flags & EXT4_FL_USER_VISIBLE;

fs/stat.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,15 @@ EXPORT_SYMBOL(generic_fill_statx_attr);
136136
* @stat: Where to fill in the attribute flags
137137
* @unit_min: Minimum supported atomic write length in bytes
138138
* @unit_max: Maximum supported atomic write length in bytes
139+
* @unit_max_opt: Optimised maximum supported atomic write length in bytes
139140
*
140141
* Fill in the STATX{_ATTR}_WRITE_ATOMIC flags in the kstat structure from
141142
* atomic write unit_min and unit_max values.
142143
*/
143144
void generic_fill_statx_atomic_writes(struct kstat *stat,
144145
unsigned int unit_min,
145-
unsigned int unit_max)
146+
unsigned int unit_max,
147+
unsigned int unit_max_opt)
146148
{
147149
/* Confirm that the request type is known */
148150
stat->result_mask |= STATX_WRITE_ATOMIC;
@@ -153,6 +155,7 @@ void generic_fill_statx_atomic_writes(struct kstat *stat,
153155
if (unit_min) {
154156
stat->atomic_write_unit_min = unit_min;
155157
stat->atomic_write_unit_max = unit_max;
158+
stat->atomic_write_unit_max_opt = unit_max_opt;
156159
/* Initially only allow 1x segment */
157160
stat->atomic_write_segments_max = 1;
158161

@@ -732,6 +735,7 @@ cp_statx(const struct kstat *stat, struct statx __user *buffer)
732735
tmp.stx_atomic_write_unit_min = stat->atomic_write_unit_min;
733736
tmp.stx_atomic_write_unit_max = stat->atomic_write_unit_max;
734737
tmp.stx_atomic_write_segments_max = stat->atomic_write_segments_max;
738+
tmp.stx_atomic_write_unit_max_opt = stat->atomic_write_unit_max_opt;
735739

736740
return copy_to_user(buffer, &tmp, sizeof(tmp)) ? -EFAULT : 0;
737741
}

fs/xfs/xfs_iops.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,7 @@ xfs_report_atomic_write(
610610

611611
if (xfs_inode_can_atomicwrite(ip))
612612
unit_min = unit_max = ip->i_mount->m_sb.sb_blocksize;
613-
generic_fill_statx_atomic_writes(stat, unit_min, unit_max);
613+
generic_fill_statx_atomic_writes(stat, unit_min, unit_max, 0);
614614
}
615615

616616
STATIC int

include/linux/fs.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3475,7 +3475,8 @@ void generic_fillattr(struct mnt_idmap *, u32, struct inode *, struct kstat *);
34753475
void generic_fill_statx_attr(struct inode *inode, struct kstat *stat);
34763476
void generic_fill_statx_atomic_writes(struct kstat *stat,
34773477
unsigned int unit_min,
3478-
unsigned int unit_max);
3478+
unsigned int unit_max,
3479+
unsigned int unit_max_opt);
34793480
extern int vfs_getattr_nosec(const struct path *, struct kstat *, u32, unsigned int);
34803481
extern int vfs_getattr(const struct path *, struct kstat *, u32, unsigned int);
34813482
void __inode_add_bytes(struct inode *inode, loff_t bytes);

include/linux/stat.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ struct kstat {
5757
u32 dio_read_offset_align;
5858
u32 atomic_write_unit_min;
5959
u32 atomic_write_unit_max;
60+
u32 atomic_write_unit_max_opt;
6061
u32 atomic_write_segments_max;
6162
};
6263

include/uapi/linux/stat.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,12 @@ struct statx {
182182
/* File offset alignment for direct I/O reads */
183183
__u32 stx_dio_read_offset_align;
184184

185-
/* 0xb8 */
186-
__u64 __spare3[9]; /* Spare space for future expansion */
185+
/* Optimised max atomic write unit in bytes */
186+
__u32 stx_atomic_write_unit_max_opt;
187+
__u32 __spare2[1];
188+
189+
/* 0xc0 */
190+
__u64 __spare3[8]; /* Spare space for future expansion */
187191

188192
/* 0x100 */
189193
};

0 commit comments

Comments
 (0)