• Miao Xie's avatar
    Btrfs: fix wrong outstanding_extents when doing DIO write · 172a5049
    Miao Xie authored
    When running the 083th case of xfstests on the filesystem with
    "compress-force=lzo", the following WARNINGs were triggered.
      WARNING: at fs/btrfs/inode.c:7908
      WARNING: at fs/btrfs/inode.c:7909
      WARNING: at fs/btrfs/inode.c:7911
      WARNING: at fs/btrfs/extent-tree.c:4510
      WARNING: at fs/btrfs/extent-tree.c:4511
    
    This problem was introduced by the patch "Btrfs: fix deadlock due
    to unsubmitted". In this patch, there are two bugs which caused
    the above problem.
    
    The 1st one is a off-by-one bug, if the DIO write return 0, it is
    also a short write, we need release the reserved space for it. But
    we didn't do it in that patch. Fix it by change "ret > 0" to
    "ret >= 0".
    
    The 2nd one is ->outstanding_extents was increased twice when
    a short write happened. As we know, ->outstanding_extents is
    a counter to keep track of the number of extent items we may
    use duo to delalloc, when we reserve the free space for a
    delalloc write, we assume that the write will introduce just
    one extent item, so we increase ->outstanding_extents by 1 at
    that time. And then we will increase it every time we split the
    write, it is done at the beginning of btrfs_get_blocks_direct().
    So when a short write happens, we needn't increase
    ->outstanding_extents again. But this patch done.
    
    In order to fix the 2nd problem, I re-write the logic for
    ->outstanding_extents operation. We don't increase it at the
    beginning of btrfs_get_blocks_direct(), instead, we just
    increase it when the split actually happens.
    Reported-by: default avatarMitch Harder <mitch.harder@sabayonlinux.org>
    Signed-off-by: default avatarMiao Xie <miaox@cn.fujitsu.com>
    Signed-off-by: default avatarChris Mason <chris.mason@fusionio.com>
    172a5049
inode.c 231 KB