• Jan Kara's avatar
    ext4: pre-zero allocated blocks for DAX IO · 12735f88
    Jan Kara authored
    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: default avatarJan Kara <jack@suse.cz>
    Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
    12735f88
inode.c 167 KB