diff options
| author | Jan Kara <jack@suse.cz> | 2026-07-27 12:49:21 +0200 |
|---|---|---|
| committer | Christian Brauner <brauner@kernel.org> | 2026-07-27 16:25:31 +0200 |
| commit | 5a499dad2c794c19bf8ad51429dce1d53d9d3e12 (patch) | |
| tree | 5da3f723279a93c1496b6de68d4ab2bb185e740e /fs/buffer.c | |
| parent | b0bca4e95b03438cd2c20bb7be3e6e109d1a01fa (diff) | |
fs: Fix missed inode writeback when racing with __writeback_single_inode
When mmb_fsync_noflush() or simple_fsync_noflush() race with another
writeback of the same inode, they can see inode dirty bits are already
clear and skip inode writeback although the racing
__writeback_single_inode() didn't yet get to writing anything. This can
result in fsync(2) returning without properly persisting the inode.
We already have I_SYNC bit for this synchronization and
writeback_single_inode() properly uses it so just fix
mmb_fsync_noflush() and simple_fsync_noflush() to take it into account
as well.
Signed-off-by: Jan Kara <jack@suse.cz>
Link: https://patch.msgid.link/20260727104923.3828017-23-jack@suse.cz
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Diffstat (limited to 'fs/buffer.c')
| -rw-r--r-- | fs/buffer.c | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/fs/buffer.c b/fs/buffer.c index daaa6614a6d6..7e5ad9f4754d 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -655,9 +655,10 @@ int mmb_fsync_noflush(struct file *file, struct mapping_metadata_bhs *mmb, if (mmb) ret = mmb_sync(mmb); - if (!(inode_state_read_once(inode) & I_DIRTY_ALL)) + if (!(inode_state_read_once(inode) & (I_DIRTY_ALL | I_SYNC))) goto out; - if (datasync && !(inode_state_read_once(inode) & I_DIRTY_DATASYNC)) + if (datasync && + !(inode_state_read_once(inode) & (I_DIRTY_DATASYNC | I_SYNC))) goto out; err = sync_inode_metadata(inode, 1); |
