From: Zhang Yi <yi.zhang@xxxxxxxxxx> Commit 'd2dc317d564a ("ext4: fix data corruption caused by unwritten and delayed extents")' fix a data corruption issue by stop passing delayed status into ext4_es_insert_extent() if the mapping range has been written. This patch change it to still pass the real delayed status and deal with the 'delayed && written' case in ext4_es_insert_extent(). If the status have delayed bit is set, it means that the path of delayed allocation is still running, and this insert process is not allocating delayed allocated blocks. Signed-off-by: Zhang Yi <yi.zhang@xxxxxxxxxx> --- fs/ext4/extents_status.c | 13 +++++++------ fs/ext4/inode.c | 2 -- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c index 3a004ed04570..62191c772b82 100644 --- a/fs/ext4/extents_status.c +++ b/fs/ext4/extents_status.c @@ -873,13 +873,14 @@ void ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk, BUG_ON(end < lblk); + /* + * Insert extent as delayed and written which can potentially cause + * data lose, and the extent has been written, it's safe to remove + * the delayed flag even it's still delayed. + */ if ((status & EXTENT_STATUS_DELAYED) && - (status & EXTENT_STATUS_WRITTEN)) { - ext4_warning(inode->i_sb, "Inserting extent [%u/%u] as " - " delayed and written which can potentially " - " cause data loss.", lblk, len); - WARN_ON(1); - } + (status & EXTENT_STATUS_WRITTEN)) + status &= ~EXTENT_STATUS_DELAYED; newes.es_lblk = lblk; newes.es_len = len; diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 6c490f05e2ba..82115d6656d3 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -563,7 +563,6 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, status = map->m_flags & EXT4_MAP_UNWRITTEN ? EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN; if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) && - !(status & EXTENT_STATUS_WRITTEN) && ext4_es_scan_range(inode, &ext4_es_is_delayed, map->m_lblk, map->m_lblk + map->m_len - 1)) status |= EXTENT_STATUS_DELAYED; @@ -673,7 +672,6 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, status = map->m_flags & EXT4_MAP_UNWRITTEN ? EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN; if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) && - !(status & EXTENT_STATUS_WRITTEN) && ext4_es_scan_range(inode, &ext4_es_is_delayed, map->m_lblk, map->m_lblk + map->m_len - 1)) status |= EXTENT_STATUS_DELAYED; -- 2.39.2