ext4: pre-zero allocated blocks for DAX IO
authorJan Kara <jack@suse.cz>
Fri, 13 May 2016 04:51:15 +0000 (00:51 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Fri, 13 May 2016 04:51:15 +0000 (00:51 -0400)
commit12735f881952c32b31bc4e433768f18489f79ec9
treedd23e6d522644d094af930a68132d8071a5de05c
parent914f82a32d026884743fb3de9f6f0a5908a9d5dd
ext4: pre-zero allocated blocks for DAX IO

Currently ext4 treats DAX IO the same way as direct IO. I.e., it
allocates unwritten extents before IO is done and converts unwritten
extents afterwards. However this way DAX IO can race with page fault to
the same area:

ext4_ext_direct_IO() dax_fault()
  dax_io()
    get_block() - allocates unwritten extent
    copy_from_iter_pmem()
  get_block() - converts
    unwritten block to
    written and zeroes it
    out
  ext4_convert_unwritten_extents()

So data written with DAX IO gets lost. Similarly dax_new_buf() called
from dax_io() can overwrite data that has been already written to the
block via mmap.

Fix the problem by using pre-zeroed blocks for DAX IO the same way as we
use them for DAX mmap. The downside of this solution is that every
allocating write writes each block twice (once zeros, once data). Fixing
the race with locking is possible as well however we would need to
lock-out faults for the whole range written to by DAX IO. And that is
not easy to do without locking-out faults for the whole file which seems
too aggressive.

Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
fs/ext4/ext4.h
fs/ext4/file.c
fs/ext4/inode.c