* Patch "ext4: fix data corruption caused by unwritten and delayed extents" has been added to the 3.10-stable tree
@ 2015-05-09 17:24 gregkh
0 siblings, 0 replies; only message in thread
From: gregkh @ 2015-05-09 17:24 UTC (permalink / raw)
To: lczerner, gregkh, tytso; +Cc: stable, stable-commits
This is a note to let you know that I've just added the patch titled
ext4: fix data corruption caused by unwritten and delayed extents
to the 3.10-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
ext4-fix-data-corruption-caused-by-unwritten-and-delayed-extents.patch
and it can be found in the queue-3.10 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@vger.kernel.org> know about it.
>From d2dc317d564a46dfc683978a2e5a4f91434e9711 Mon Sep 17 00:00:00 2001
From: Lukas Czerner <lczerner@redhat.com>
Date: Sat, 2 May 2015 21:36:55 -0400
Subject: ext4: fix data corruption caused by unwritten and delayed extents
From: Lukas Czerner <lczerner@redhat.com>
commit d2dc317d564a46dfc683978a2e5a4f91434e9711 upstream.
Currently it is possible to lose whole file system block worth of data
when we hit the specific interaction with unwritten and delayed extents
in status extent tree.
The problem is that when we insert delayed extent into extent status
tree the only way to get rid of it is when we write out delayed buffer.
However there is a limitation in the extent status tree implementation
so that when inserting unwritten extent should there be even a single
delayed block the whole unwritten extent would be marked as delayed.
At this point, there is no way to get rid of the delayed extents,
because there are no delayed buffers to write out. So when a we write
into said unwritten extent we will convert it to written, but it still
remains delayed.
When we try to write into that block later ext4_da_map_blocks() will set
the buffer new and delayed and map it to invalid block which causes
the rest of the block to be zeroed loosing already written data.
For now we can fix this by simply not allowing to set delayed status on
written extent in the extent status tree. Also add WARN_ON() to make
sure that we notice if this happens in the future.
This problem can be easily reproduced by running the following xfs_io.
xfs_io -f -c "pwrite -S 0xaa 4096 2048" \
-c "falloc 0 131072" \
-c "pwrite -S 0xbb 65536 2048" \
-c "fsync" /mnt/test/fff
echo 3 > /proc/sys/vm/drop_caches
xfs_io -c "pwrite -S 0xdd 67584 2048" /mnt/test/fff
This can be theoretically also reproduced by at random by running fsx,
but it's not very reliable, though on machines with bigger page size
(like ppc) this can be seen more often (especially xfstest generic/127)
Signed-off-by: Lukas Czerner <lczerner@redhat.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/ext4/extents_status.c | 8 ++++++++
fs/ext4/inode.c | 2 ++
2 files changed, 10 insertions(+)
--- a/fs/ext4/extents_status.c
+++ b/fs/ext4/extents_status.c
@@ -655,6 +655,14 @@ int ext4_es_insert_extent(struct inode *
BUG_ON(end < lblk);
+ 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.\n", lblk, len);
+ WARN_ON(1);
+ }
+
newes.es_lblk = lblk;
newes.es_len = len;
ext4_es_store_pblock(&newes, pblk);
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -626,6 +626,7 @@ int ext4_map_blocks(handle_t *handle, st
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_find_delalloc_range(inode, map->m_lblk,
map->m_lblk + map->m_len - 1))
status |= EXTENT_STATUS_DELAYED;
@@ -736,6 +737,7 @@ found:
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_find_delalloc_range(inode, map->m_lblk,
map->m_lblk + map->m_len - 1))
status |= EXTENT_STATUS_DELAYED;
Patches currently in stable-queue which might be from lczerner@redhat.com are
queue-3.10/ext4-fix-data-corruption-caused-by-unwritten-and-delayed-extents.patch
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2015-05-09 17:24 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-05-09 17:24 Patch "ext4: fix data corruption caused by unwritten and delayed extents" has been added to the 3.10-stable tree gregkh
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).