From: Greg Kroah-Hartman Date: Fri, 7 May 2021 15:31:11 +0000 (+0200) Subject: 4.9-stable patches X-Git-Tag: v5.4.118~97 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1f952ebd36ad80655262d26a9c7074c3685542a7;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: btrfs-fix-metadata-extent-leak-after-failure-to-create-subvolume.patch --- diff --git a/queue-4.9/btrfs-fix-metadata-extent-leak-after-failure-to-create-subvolume.patch b/queue-4.9/btrfs-fix-metadata-extent-leak-after-failure-to-create-subvolume.patch new file mode 100644 index 00000000000..e349fca0f5c --- /dev/null +++ b/queue-4.9/btrfs-fix-metadata-extent-leak-after-failure-to-create-subvolume.patch @@ -0,0 +1,95 @@ +From 67addf29004c5be9fa0383c82a364bb59afc7f84 Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Tue, 20 Apr 2021 10:55:12 +0100 +Subject: btrfs: fix metadata extent leak after failure to create subvolume + +From: Filipe Manana + +commit 67addf29004c5be9fa0383c82a364bb59afc7f84 upstream. + +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: Filipe Manana +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman +--- + fs/btrfs/ioctl.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -557,8 +557,6 @@ static noinline int create_subvol(struct + btrfs_set_root_otransid(root_item, trans->transid); + + btrfs_tree_unlock(leaf); +- free_extent_buffer(leaf); +- leaf = NULL; + + btrfs_set_root_dirid(root_item, new_dirid); + +@@ -567,8 +565,22 @@ static noinline int create_subvol(struct + key.type = BTRFS_ROOT_ITEM_KEY; + ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key, + root_item); +- if (ret) ++ if (ret) { ++ /* ++ * Since we don't abort the transaction in this case, free the ++ * tree block so that we don't leak space and leave the ++ * filesystem in an inconsistent state (an extent item in the ++ * extent tree without backreferences). Also no need to have ++ * the tree block locked since it is not in any tree at this ++ * point, so no other task can find it and use it. ++ */ ++ btrfs_free_tree_block(trans, root, leaf, 0, 1); ++ free_extent_buffer(leaf); + goto fail; ++ } ++ ++ free_extent_buffer(leaf); ++ leaf = NULL; + + key.offset = (u64)-1; + new_root = btrfs_read_fs_root_no_name(root->fs_info, &key); diff --git a/queue-4.9/series b/queue-4.9/series index a80970bf178..feb98e1c8a5 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -11,3 +11,4 @@ arm64-dts-mt8173-fix-property-typo-of-phys-in-dsi-node.patch ecryptfs-fix-kernel-panic-with-null-dev_name.patch mmc-core-do-a-power-cycle-when-the-cmd11-fails.patch mmc-core-set-read-only-for-sd-cards-with-permanent-write-protect-bit.patch +btrfs-fix-metadata-extent-leak-after-failure-to-create-subvolume.patch