1. 20 6月, 2017 38 次提交
  2. 10 6月, 2017 2 次提交
    • O
      Btrfs: fix delalloc accounting leak caused by u32 overflow · 70e7af24
      Omar Sandoval 提交于
      btrfs_calc_trans_metadata_size() does an unsigned 32-bit multiplication,
      which can overflow if num_items >= 4 GB / (nodesize * BTRFS_MAX_LEVEL * 2).
      For a nodesize of 16kB, this overflow happens at 16k items. Usually,
      num_items is a small constant passed to btrfs_start_transaction(), but
      we also use btrfs_calc_trans_metadata_size() for metadata reservations
      for extent items in btrfs_delalloc_{reserve,release}_metadata().
      
      In drop_outstanding_extents(), num_items is calculated as
      inode->reserved_extents - inode->outstanding_extents. The difference
      between these two counters is usually small, but if many delalloc
      extents are reserved and then the outstanding extents are merged in
      btrfs_merge_extent_hook(), the difference can become large enough to
      overflow in btrfs_calc_trans_metadata_size().
      
      The overflow manifests itself as a leak of a multiple of 4 GB in
      delalloc_block_rsv and the metadata bytes_may_use counter. This in turn
      can cause early ENOSPC errors. Additionally, these WARN_ONs in
      extent-tree.c will be hit when unmounting:
      
          WARN_ON(fs_info->delalloc_block_rsv.size > 0);
          WARN_ON(fs_info->delalloc_block_rsv.reserved > 0);
          WARN_ON(space_info->bytes_pinned > 0 ||
                  space_info->bytes_reserved > 0 ||
                  space_info->bytes_may_use > 0);
      
      Fix it by casting nodesize to a u64 so that
      btrfs_calc_trans_metadata_size() does a full 64-bit multiplication.
      While we're here, do the same in btrfs_calc_trunc_metadata_size(); this
      can't overflow with any existing uses, but it's better to be safe here
      than have another hard-to-debug problem later on.
      
      Cc: stable@vger.kernel.org
      Signed-off-by: NOmar Sandoval <osandov@fb.com>
      Reviewed-by: NDavid Sterba <dsterba@suse.com>
      Signed-off-by: NChris Mason <clm@fb.com>
      70e7af24
    • L
      Btrfs: clear EXTENT_DEFRAG bits in finish_ordered_io · 452e62b7
      Liu Bo 提交于
      Before this, we use 'filled' mode here, ie. if all range has been
      filled with EXTENT_DEFRAG bits, get to clear it, but if the defrag
      range joins the adjacent delalloc range, then we'll have EXTENT_DEFRAG
      bits in extent_state until releasing this inode's pages, and that
      prevents extent_data from being freed.
      
      This clears the bit if any was found within the ordered extent.
      Signed-off-by: NLiu Bo <bo.li.liu@oracle.com>
      Reviewed-by: NDavid Sterba <dsterba@suse.com>
      Signed-off-by: NDavid Sterba <dsterba@suse.com>
      Signed-off-by: NChris Mason <clm@fb.com>
      452e62b7