• Qu Wenruo's avatar
    btrfs: subpage: disable inline extent creation · 7367253a
    Qu Wenruo authored
    [BUG]
    When running the following fsx command (extracted from generic/127) on
    subpage filesystem, it can create inline extent with regular extents:
    
      fsx -q -l 262144 -o 65536 -S 191110531 -N 9057 -R -W $mnt/file > /tmp/fsx
    
    The offending extent would look like:
    
      item 9 key (257 INODE_REF 256) itemoff 15703 itemsize 14
        index 2 namelen 4 name: file
      item 10 key (257 EXTENT_DATA 0) itemoff 14975 itemsize 728
        generation 7 type 0 (inline)
        inline extent data size 707 ram_bytes 707 compression 0 (none)
      item 11 key (257 EXTENT_DATA 4096) itemoff 14922 itemsize 53
        generation 7 type 2 (prealloc)
        prealloc data disk byte 102346752 nr 4096
        prealloc data offset 0 nr 4096
    
    [CAUSE]
    For subpage filesystem, the writeback is triggered in page units, which
    means, even if we just want to writeback range [16K, 20K) for 64K page
    system, we will still try to writeback any dirty sector of range [0, 64K).
    
    This is never a problem if sectorsize == PAGE_SIZE, but for subpage,
    this can cause unexpected problems.
    
    For above test case, the last several operations from fsx are:
    
     9055 trunc      from 0x40000 to 0x2c3
     9057 falloc     from 0x164c to 0x19d2 (0x386 bytes)
    
    In operation 9055, we dirtied sector [0, 4096), then in falloc, we call
    btrfs_wait_ordered_range(inode, start=4096, len=4096), only expecting to
    writeback any dirty data in [4096, 8192), but nothing else.
    
    Unfortunately, in subpage case, above btrfs_wait_ordered_range() will
    trigger writeback of the range [0, 64K), which includes the data at
    [0, 4096).
    
    And since at the call site, we haven't yet increased i_size, which is
    still 707, this means cow_file_range() can insert an inline extent.
    
    Resulting above inline + regular extent.
    
    [WORKAROUND]
    I don't really have any good short-term solution yet, as this means all
    operations that would trigger writeback need to be reviewed for any
    i_size change.
    
    So here I choose to disable inline extent creation for subpage case as a
    workaround.  We have done tons of work just to avoid such extent, so I
    don't to create an exception just for subpage.
    
    This only affects inline extent creation, subpage has no problem reading
    existing inline extents at all.
    Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    7367253a
inode.c 304 KB