• F
    btrfs: fix metadata extent leak after failure to create subvolume · 67addf29
    Filipe Manana 提交于
    When creating a subvolume we allocate an extent buffer for its root node
    after starting a transaction. We setup a root item for the subvolume that
    points to that extent buffer and then attempt to insert the root item into
    the root tree - however if that fails, due to ENOMEM for example, we do
    not free the extent buffer previously allocated and we do not abort the
    transaction (as at that point we did nothing that can not be undone).
    
    This means that we effectively do not return the metadata extent back to
    the free space cache/tree and we leave a delayed reference for it which
    causes a metadata extent item to be added to the extent tree, in the next
    transaction commit, without having backreferences. When this happens
    'btrfs check' reports the following:
    
      $ btrfs check /dev/sdi
      Opening filesystem to check...
      Checking filesystem on /dev/sdi
      UUID: dce2cb9d-025f-4b05-a4bf-cee0ad3785eb
      [1/7] checking root items
      [2/7] checking extents
      ref mismatch on [30425088 16384] extent item 1, found 0
      backref 30425088 root 256 not referenced back 0x564a91c23d70
      incorrect global backref count on 30425088 found 1 wanted 0
      backpointer mismatch on [30425088 16384]
      owner ref check failed [30425088 16384]
      ERROR: errors found in extent allocation tree or chunk allocation
      [3/7] checking free space cache
      [4/7] checking fs roots
      [5/7] checking only csums items (without verifying data)
      [6/7] checking root refs
      [7/7] checking quota groups skipped (not enabled on this FS)
      found 212992 bytes used, error(s) found
      total csum bytes: 0
      total tree bytes: 131072
      total fs tree bytes: 32768
      total extent tree bytes: 16384
      btree space waste bytes: 124669
      file data blocks allocated: 65536
       referenced 65536
    
    So fix this by freeing the metadata extent if btrfs_insert_root() returns
    an error.
    
    CC: stable@vger.kernel.org # 4.4+
    Signed-off-by: NFilipe Manana <fdmanana@suse.com>
    Reviewed-by: NDavid Sterba <dsterba@suse.com>
    Signed-off-by: NDavid Sterba <dsterba@suse.com>
    67addf29
ioctl.c 123.1 KB