Skip to content

Commit

Permalink
ext4: iomap that extends beyond EOF should be marked dirty
Browse files Browse the repository at this point in the history
This patch addresses what Dave Chinner had discovered and fixed within
commit: 7684e2c. This changes does not have any user visible
impact for ext4 as none of the current users of ext4_iomap_begin()
that extend files depend on IOMAP_F_DIRTY.

When doing a direct IO that spans the current EOF, and there are
written blocks beyond EOF that extend beyond the current write, the
only metadata update that needs to be done is a file size extension.

However, we don't mark such iomaps as IOMAP_F_DIRTY to indicate that
there is IO completion metadata updates required, and hence we may
fail to correctly sync file size extensions made in IO completion when
O_DSYNC writes are being used and the hardware supports FUA.

Hence when setting IOMAP_F_DIRTY, we need to also take into account
whether the iomap spans the current EOF. If it does, then we need to
mark it dirty so that IO completion will call generic_write_sync() to
flush the inode size update to stable storage correctly.

Signed-off-by: Matthew Bobrowski <mbobrowski@mbobrowski.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Ritesh Harjani <riteshh@linux.ibm.com>
Link: https://lore.kernel.org/r/8b43ee9ee94bee5328da56ba0909b7d2229ef150.1572949325.git.mbobrowski@mbobrowski.org
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
  • Loading branch information
Matthew Bobrowski authored and Theodore Ts'o committed Nov 5, 2019
1 parent 548feeb commit 2e9b51d
Showing 1 changed file with 7 additions and 1 deletion.
8 changes: 7 additions & 1 deletion fs/ext4/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -3565,8 +3565,14 @@ static int ext4_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
return ret;
}

/*
* Writes that span EOF might trigger an I/O size update on completion,
* so consider them to be dirty for the purposes of O_DSYNC, even if
* there is no other metadata changes being made or are pending here.
*/
iomap->flags = 0;
if (ext4_inode_datasync_dirty(inode))
if (ext4_inode_datasync_dirty(inode) ||
offset + length > i_size_read(inode))
iomap->flags |= IOMAP_F_DIRTY;
iomap->bdev = inode->i_sb->s_bdev;
iomap->dax_dev = sbi->s_daxdev;
Expand Down

0 comments on commit 2e9b51d

Please sign in to comment.