• Jan Kara's avatar
    dax: New fault locking · ac401cc7
    Jan Kara authored
    Currently DAX page fault locking is racy.
    
    CPU0 (write fault)		CPU1 (read fault)
    
    __dax_fault()			__dax_fault()
      get_block(inode, block, &bh, 0) -> not mapped
    				  get_block(inode, block, &bh, 0)
    				    -> not mapped
      if (!buffer_mapped(&bh))
        if (vmf->flags & FAULT_FLAG_WRITE)
          get_block(inode, block, &bh, 1) -> allocates blocks
      if (page) -> no
    				  if (!buffer_mapped(&bh))
    				    if (vmf->flags & FAULT_FLAG_WRITE) {
    				    } else {
    				      dax_load_hole();
    				    }
      dax_insert_mapping()
    
    And we are in a situation where we fail in dax_radix_entry() with -EIO.
    
    Another problem with the current DAX page fault locking is that there is
    no race-free way to clear dirty tag in the radix tree. We can always
    end up with clean radix tree and dirty data in CPU cache.
    
    We fix the first problem by introducing locking of exceptional radix
    tree entries in DAX mappings acting very similarly to page lock and thus
    synchronizing properly faults against the same mapping index. The same
    lock can later be used to avoid races when clearing radix tree dirty
    tag.
    Reviewed-by: default avatarNeilBrown <neilb@suse.com>
    Reviewed-by: default avatarRoss Zwisler <ross.zwisler@linux.intel.com>
    Signed-off-by: default avatarJan Kara <jack@suse.cz>
    Signed-off-by: default avatarRoss Zwisler <ross.zwisler@linux.intel.com>
    ac401cc7
dax.c 36 KB