Commit edf6b0e1 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull btrfs fixes from David Sterba:
 "A few more fixes:

   - regression fix for a crash after failed snapshot creation

   - one more lockep fix: use nofs allocation when allocating missing
     device

   - fix reloc tree leak on degraded mount

   - make some extent buffer alignment checks less strict to mount
     filesystems created by btrfs-convert"

* tag 'for-5.9-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: fix NULL pointer dereference after failure to create snapshot
  btrfs: free data reloc tree on failed mount
  btrfs: require only sector size alignment for parent eb bytenr
  btrfs: fix lockdep splat in add_missing_dev
parents 5a3c558a 2d892ccd
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -3418,6 +3418,8 @@ fail_block_groups:
	btrfs_put_block_group_cache(fs_info);

fail_tree_roots:
	if (fs_info->data_reloc_root)
		btrfs_drop_and_free_fs_root(fs_info, fs_info->data_reloc_root);
	free_root_pointers(fs_info, true);
	invalidate_inode_pages2(fs_info->btree_inode->i_mapping);

+9 −10
Original line number Diff line number Diff line
@@ -400,12 +400,11 @@ int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb,
			if (type == BTRFS_SHARED_BLOCK_REF_KEY) {
				ASSERT(eb->fs_info);
				/*
				 * Every shared one has parent tree
				 * block, which must be aligned to
				 * nodesize.
				 * Every shared one has parent tree block,
				 * which must be aligned to sector size.
				 */
				if (offset &&
				    IS_ALIGNED(offset, eb->fs_info->nodesize))
				    IS_ALIGNED(offset, eb->fs_info->sectorsize))
					return type;
			}
		} else if (is_data == BTRFS_REF_TYPE_DATA) {
@@ -414,12 +413,11 @@ int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb,
			if (type == BTRFS_SHARED_DATA_REF_KEY) {
				ASSERT(eb->fs_info);
				/*
				 * Every shared one has parent tree
				 * block, which must be aligned to
				 * nodesize.
				 * Every shared one has parent tree block,
				 * which must be aligned to sector size.
				 */
				if (offset &&
				    IS_ALIGNED(offset, eb->fs_info->nodesize))
				    IS_ALIGNED(offset, eb->fs_info->sectorsize))
					return type;
			}
		} else {
@@ -429,8 +427,9 @@ int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb,
	}

	btrfs_print_leaf((struct extent_buffer *)eb);
	btrfs_err(eb->fs_info, "eb %llu invalid extent inline ref type %d",
		  eb->start, type);
	btrfs_err(eb->fs_info,
		  "eb %llu iref 0x%lx invalid extent inline ref type %d",
		  eb->start, (unsigned long)iref, type);
	WARN_ON(1);

	return BTRFS_REF_TYPE_INVALID;
+7 −5
Original line number Diff line number Diff line
@@ -95,9 +95,10 @@ static void print_extent_item(struct extent_buffer *eb, int slot, int type)
			 * offset is supposed to be a tree block which
			 * must be aligned to nodesize.
			 */
			if (!IS_ALIGNED(offset, eb->fs_info->nodesize))
				pr_info("\t\t\t(parent %llu is NOT ALIGNED to nodesize %llu)\n",
					offset, (unsigned long long)eb->fs_info->nodesize);
			if (!IS_ALIGNED(offset, eb->fs_info->sectorsize))
				pr_info(
			"\t\t\t(parent %llu not aligned to sectorsize %u)\n",
					offset, eb->fs_info->sectorsize);
			break;
		case BTRFS_EXTENT_DATA_REF_KEY:
			dref = (struct btrfs_extent_data_ref *)(&iref->offset);
@@ -112,8 +113,9 @@ static void print_extent_item(struct extent_buffer *eb, int slot, int type)
			 * must be aligned to nodesize.
			 */
			if (!IS_ALIGNED(offset, eb->fs_info->nodesize))
				pr_info("\t\t\t(parent %llu is NOT ALIGNED to nodesize %llu)\n",
				     offset, (unsigned long long)eb->fs_info->nodesize);
				pr_info(
			"\t\t\t(parent %llu not aligned to sectorsize %u)\n",
				     offset, eb->fs_info->sectorsize);
			break;
		default:
			pr_cont("(extent %llu has INVALID ref type %d)\n",
+1 −0
Original line number Diff line number Diff line
@@ -1636,6 +1636,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
	pending->snap = btrfs_get_new_fs_root(fs_info, objectid, pending->anon_dev);
	if (IS_ERR(pending->snap)) {
		ret = PTR_ERR(pending->snap);
		pending->snap = NULL;
		btrfs_abort_transaction(trans, ret);
		goto fail;
	}
+10 −0
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@
 */

#include <linux/sched.h>
#include <linux/sched/mm.h>
#include <linux/bio.h>
#include <linux/slab.h>
#include <linux/blkdev.h>
@@ -6484,8 +6485,17 @@ static struct btrfs_device *add_missing_dev(struct btrfs_fs_devices *fs_devices,
					    u64 devid, u8 *dev_uuid)
{
	struct btrfs_device *device;
	unsigned int nofs_flag;

	/*
	 * We call this under the chunk_mutex, so we want to use NOFS for this
	 * allocation, however we don't want to change btrfs_alloc_device() to
	 * always do NOFS because we use it in a lot of other GFP_KERNEL safe
	 * places.
	 */
	nofs_flag = memalloc_nofs_save();
	device = btrfs_alloc_device(NULL, &devid, dev_uuid);
	memalloc_nofs_restore(nofs_flag);
	if (IS_ERR(device))
		return device;