Skip to content

Commit 6dfc1c1

Browse files
riteshharjaniDarrick J. Wong
authored andcommitted
ext4: Add statx support for atomic writes
This patch adds base support for atomic writes via statx getattr. On bs < ps systems, we can create FS with say bs of 16k. That means both atomic write min and max unit can be set to 16k for supporting atomic writes. Co-developed-by: Ojaswin Mujoo <[email protected]> Signed-off-by: Ojaswin Mujoo <[email protected]> Signed-off-by: Ritesh Harjani (IBM) <[email protected]> Reviewed-by: Darrick J. Wong <[email protected]> Signed-off-by: Darrick J. Wong <[email protected]> Reviewed-by: Jan Kara <[email protected]>
1 parent 3af5298 commit 6dfc1c1

File tree

3 files changed

+53
-0
lines changed

3 files changed

+53
-0
lines changed

fs/ext4/ext4.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1729,6 +1729,10 @@ struct ext4_sb_info {
17291729
*/
17301730
struct work_struct s_sb_upd_work;
17311731

1732+
/* Atomic write unit values in bytes */
1733+
unsigned int s_awu_min;
1734+
unsigned int s_awu_max;
1735+
17321736
/* Ext4 fast commit sub transaction ID */
17331737
atomic_t s_fc_subtid;
17341738

@@ -3855,6 +3859,12 @@ static inline int ext4_buffer_uptodate(struct buffer_head *bh)
38553859
return buffer_uptodate(bh);
38563860
}
38573861

3862+
static inline bool ext4_inode_can_atomic_write(struct inode *inode)
3863+
{
3864+
3865+
return S_ISREG(inode->i_mode) && EXT4_SB(inode->i_sb)->s_awu_min > 0;
3866+
}
3867+
38583868
extern int ext4_block_write_begin(handle_t *handle, struct folio *folio,
38593869
loff_t pos, unsigned len,
38603870
get_block_t *get_block);

fs/ext4/inode.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5578,6 +5578,18 @@ int ext4_getattr(struct mnt_idmap *idmap, const struct path *path,
55785578
}
55795579
}
55805580

5581+
if ((request_mask & STATX_WRITE_ATOMIC) && S_ISREG(inode->i_mode)) {
5582+
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
5583+
unsigned int awu_min = 0, awu_max = 0;
5584+
5585+
if (ext4_inode_can_atomic_write(inode)) {
5586+
awu_min = sbi->s_awu_min;
5587+
awu_max = sbi->s_awu_max;
5588+
}
5589+
5590+
generic_fill_statx_atomic_writes(stat, awu_min, awu_max);
5591+
}
5592+
55815593
flags = ei->i_flags & EXT4_FL_USER_VISIBLE;
55825594
if (flags & EXT4_APPEND_FL)
55835595
stat->attributes |= STATX_ATTR_APPEND;

fs/ext4/super.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4425,6 +4425,36 @@ static int ext4_handle_clustersize(struct super_block *sb)
44254425
return 0;
44264426
}
44274427

4428+
/*
4429+
* ext4_atomic_write_init: Initializes filesystem min & max atomic write units.
4430+
* @sb: super block
4431+
* TODO: Later add support for bigalloc
4432+
*/
4433+
static void ext4_atomic_write_init(struct super_block *sb)
4434+
{
4435+
struct ext4_sb_info *sbi = EXT4_SB(sb);
4436+
struct block_device *bdev = sb->s_bdev;
4437+
4438+
if (!bdev_can_atomic_write(bdev))
4439+
return;
4440+
4441+
if (!ext4_has_feature_extents(sb))
4442+
return;
4443+
4444+
sbi->s_awu_min = max(sb->s_blocksize,
4445+
bdev_atomic_write_unit_min_bytes(bdev));
4446+
sbi->s_awu_max = min(sb->s_blocksize,
4447+
bdev_atomic_write_unit_max_bytes(bdev));
4448+
if (sbi->s_awu_min && sbi->s_awu_max &&
4449+
sbi->s_awu_min <= sbi->s_awu_max) {
4450+
ext4_msg(sb, KERN_NOTICE, "Supports (experimental) DIO atomic writes awu_min: %u, awu_max: %u",
4451+
sbi->s_awu_min, sbi->s_awu_max);
4452+
} else {
4453+
sbi->s_awu_min = 0;
4454+
sbi->s_awu_max = 0;
4455+
}
4456+
}
4457+
44284458
static void ext4_fast_commit_init(struct super_block *sb)
44294459
{
44304460
struct ext4_sb_info *sbi = EXT4_SB(sb);
@@ -5336,6 +5366,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
53365366

53375367
spin_lock_init(&sbi->s_bdev_wb_lock);
53385368

5369+
ext4_atomic_write_init(sb);
53395370
ext4_fast_commit_init(sb);
53405371

53415372
sb->s_root = NULL;

0 commit comments

Comments
 (0)