linux/fs/ext4
Lukas Czerner f84a0b54d2 ext4: fix data corruption caused by unwritten and delayed extents
commit d2dc317d56 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>
History 2015-05-13 05:16:57 -07:00
..
acl.c ext2/3/4: use generic posix ACL infrastructure 2014-01-25 23:58:19 -05:00
acl.h ext2/3/4: use generic posix ACL infrastructure 2014-01-25 23:58:19 -05:00
balloc.c ext4: don't count free clusters from a corrupt block group 2013-10-31 11:46:31 -04:00
bitmap.c ext4: Replace open coded mdata csum feature to helper function 2014-11-14 08:59:58 -08:00
block_validity.c fs/ext4: use rbtree postorder iteration helper instead of opencoding 2014-01-23 16:37:03 -08:00
dir.c fs/ext4: use rbtree postorder iteration helper instead of opencoding 2014-01-23 16:37:03 -08:00
ext4.h ext4: check s_chksum_driver when looking for bg csum presence 2014-11-14 08:59:58 -08:00
ext4_extents.h ext4: isolate ext4_extents.h file 2013-08-28 14:47:06 -04:00
ext4_jbd2.c ext4: call ext4_error_inode() if jbd2_journal_dirty_metadata() fails 2013-12-02 09:31:36 -05:00
ext4_jbd2.h ext4: Fix misspellings using 'codespell' tool 2013-08-28 14:40:12 -04:00
extents.c ext4: Replace open coded mdata csum feature to helper function 2014-11-14 08:59:58 -08:00
extents_status.c ext4: fix data corruption caused by unwritten and delayed extents 2015-05-13 05:16:57 -07:00
extents_status.h ext4: isolate ext4_extents.h file 2013-08-28 14:47:06 -04:00
file.c ext4: prevent bugon on race between write/fcntl 2015-02-11 14:54:48 +08:00
fsync.c ext4: Fix fsync error handling after filesystem abort 2013-06-12 22:38:04 -04:00
hash.c ext4: reduce one "if" comparison in ext4_dirhash() 2013-02-01 22:33:21 -05:00
ialloc.c ext4: fix oops when loading block bitmap failed 2014-11-14 08:59:59 -08:00
indirect.c ext4: Fix hole punching for files with indirect blocks 2014-07-09 11:18:27 -07:00
inline.c ext4: Replace open coded mdata csum feature to helper function 2014-11-14 08:59:58 -08:00
inode.c ext4: fix data corruption caused by unwritten and delayed extents 2015-05-13 05:16:57 -07:00
ioctl.c ext4: Replace open coded mdata csum feature to helper function 2014-11-14 08:59:58 -08:00
Kconfig ext4: fix Kconfig documentation for CONFIG_EXT4_DEBUG 2013-04-21 20:32:03 -04:00
Makefile ext4: Remove CONFIG_EXT4_FS_XATTR 2012-12-10 16:30:43 -05:00
mballoc.c mm: non-atomically mark page accessed during page cache allocation where possible 2015-01-29 17:40:52 -08:00
mballoc.h ext4: use module parameters instead of debugfs for mballoc_debug 2013-02-09 16:28:20 -05:00
migrate.c ext4: Fix misspellings using 'codespell' tool 2013-08-28 14:40:12 -04:00
mmp.c ext4: Replace open coded mdata csum feature to helper function 2014-11-14 08:59:58 -08:00
move_extent.c vfs: pull ext4's double-i_mutex-locking into common code 2013-11-09 00:16:39 -05:00
namei.c ext4: make fsync to sync parent dir in no-journal for real this time 2015-05-06 21:59:15 +02:00
page-io.c ext4: fix zeroing of page during writeback 2014-06-30 20:11:55 -07:00
resize.c ext4: fix overflow when updating superblock backups after resize 2014-11-14 08:59:58 -08:00
super.c ext4: enable journal checksum when metadata checksum feature enabled 2014-11-14 08:59:59 -08:00
symlink.c ext4: Remove CONFIG_EXT4_FS_XATTR 2012-12-10 16:30:43 -05:00
truncate.h ext4: move common truncate functions to header file 2011-06-27 19:16:04 -04:00
xattr.c ext4: Replace open coded mdata csum feature to helper function 2014-11-14 08:59:58 -08:00
xattr.h ext2/3/4: use generic posix ACL infrastructure 2014-01-25 23:58:19 -05:00
xattr_security.c Merge branch 'for_linus' into for_linus_merged 2012-01-10 11:54:07 -05:00
xattr_trusted.c ext2/3/4: delete unneeded includes of module.h 2012-01-09 13:52:10 +01:00
xattr_user.c ext2/3/4: delete unneeded includes of module.h 2012-01-09 13:52:10 +01:00