Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 026f830e authored by Josef Bacik's avatar Josef Bacik Committed by Greg Kroah-Hartman
Browse files

btrfs: fix double put of block group with nocow



commit 230ed397435e85b54f055c524fcb267ae2ce3bc4 upstream.

While debugging a patch that I wrote I was hitting use-after-free panics
when accessing block groups on unmount.  This turned out to be because
in the nocow case if we bail out of doing the nocow for whatever reason
we need to call btrfs_dec_nocow_writers() if we called the inc.  This
puts our block group, but a few error cases does

if (nocow) {
    btrfs_dec_nocow_writers();
    goto error;
}

unfortunately, error is

error:
	if (nocow)
		btrfs_dec_nocow_writers();

so we get a double put on our block group.  Fix this by dropping the
error cases calling of btrfs_dec_nocow_writers(), as it's handled at the
error label now.

Fixes: 762bf098 ("btrfs: improve error handling in run_delalloc_nocow")
CC: stable@vger.kernel.org # 5.4+
Reviewed-by: default avatarFilipe Manana <fdmanana@suse.com>
Signed-off-by: default avatarJosef Bacik <josef@toxicpanda.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 808b2b3e
Loading
Loading
Loading
Loading
+1 −8
Original line number Diff line number Diff line
@@ -1657,12 +1657,8 @@ static noinline int run_delalloc_nocow(struct inode *inode,
			ret = fallback_to_cow(inode, locked_page, cow_start,
					      found_key.offset - 1,
					      page_started, nr_written);
			if (ret) {
				if (nocow)
					btrfs_dec_nocow_writers(fs_info,
								disk_bytenr);
			if (ret)
				goto error;
			}
			cow_start = (u64)-1;
		}

@@ -1678,9 +1674,6 @@ static noinline int run_delalloc_nocow(struct inode *inode,
					  ram_bytes, BTRFS_COMPRESS_NONE,
					  BTRFS_ORDERED_PREALLOC);
			if (IS_ERR(em)) {
				if (nocow)
					btrfs_dec_nocow_writers(fs_info,
								disk_bytenr);
				ret = PTR_ERR(em);
				goto error;
			}