Commit edf6b0e1 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-5.9-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux

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
...@@ -3418,6 +3418,8 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device ...@@ -3418,6 +3418,8 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
btrfs_put_block_group_cache(fs_info); btrfs_put_block_group_cache(fs_info);
fail_tree_roots: 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); free_root_pointers(fs_info, true);
invalidate_inode_pages2(fs_info->btree_inode->i_mapping); invalidate_inode_pages2(fs_info->btree_inode->i_mapping);
......
...@@ -400,12 +400,11 @@ int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb, ...@@ -400,12 +400,11 @@ int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb,
if (type == BTRFS_SHARED_BLOCK_REF_KEY) { if (type == BTRFS_SHARED_BLOCK_REF_KEY) {
ASSERT(eb->fs_info); ASSERT(eb->fs_info);
/* /*
* Every shared one has parent tree * Every shared one has parent tree block,
* block, which must be aligned to * which must be aligned to sector size.
* nodesize.
*/ */
if (offset && if (offset &&
IS_ALIGNED(offset, eb->fs_info->nodesize)) IS_ALIGNED(offset, eb->fs_info->sectorsize))
return type; return type;
} }
} else if (is_data == BTRFS_REF_TYPE_DATA) { } else if (is_data == BTRFS_REF_TYPE_DATA) {
...@@ -414,12 +413,11 @@ int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb, ...@@ -414,12 +413,11 @@ int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb,
if (type == BTRFS_SHARED_DATA_REF_KEY) { if (type == BTRFS_SHARED_DATA_REF_KEY) {
ASSERT(eb->fs_info); ASSERT(eb->fs_info);
/* /*
* Every shared one has parent tree * Every shared one has parent tree block,
* block, which must be aligned to * which must be aligned to sector size.
* nodesize.
*/ */
if (offset && if (offset &&
IS_ALIGNED(offset, eb->fs_info->nodesize)) IS_ALIGNED(offset, eb->fs_info->sectorsize))
return type; return type;
} }
} else { } else {
...@@ -429,8 +427,9 @@ int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb, ...@@ -429,8 +427,9 @@ int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb,
} }
btrfs_print_leaf((struct extent_buffer *)eb); btrfs_print_leaf((struct extent_buffer *)eb);
btrfs_err(eb->fs_info, "eb %llu invalid extent inline ref type %d", btrfs_err(eb->fs_info,
eb->start, type); "eb %llu iref 0x%lx invalid extent inline ref type %d",
eb->start, (unsigned long)iref, type);
WARN_ON(1); WARN_ON(1);
return BTRFS_REF_TYPE_INVALID; return BTRFS_REF_TYPE_INVALID;
......
...@@ -95,9 +95,10 @@ static void print_extent_item(struct extent_buffer *eb, int slot, int type) ...@@ -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 * offset is supposed to be a tree block which
* must be aligned to nodesize. * must be aligned to nodesize.
*/ */
if (!IS_ALIGNED(offset, eb->fs_info->nodesize)) if (!IS_ALIGNED(offset, eb->fs_info->sectorsize))
pr_info("\t\t\t(parent %llu is NOT ALIGNED to nodesize %llu)\n", pr_info(
offset, (unsigned long long)eb->fs_info->nodesize); "\t\t\t(parent %llu not aligned to sectorsize %u)\n",
offset, eb->fs_info->sectorsize);
break; break;
case BTRFS_EXTENT_DATA_REF_KEY: case BTRFS_EXTENT_DATA_REF_KEY:
dref = (struct btrfs_extent_data_ref *)(&iref->offset); 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) ...@@ -112,8 +113,9 @@ static void print_extent_item(struct extent_buffer *eb, int slot, int type)
* must be aligned to nodesize. * must be aligned to nodesize.
*/ */
if (!IS_ALIGNED(offset, eb->fs_info->nodesize)) if (!IS_ALIGNED(offset, eb->fs_info->nodesize))
pr_info("\t\t\t(parent %llu is NOT ALIGNED to nodesize %llu)\n", pr_info(
offset, (unsigned long long)eb->fs_info->nodesize); "\t\t\t(parent %llu not aligned to sectorsize %u)\n",
offset, eb->fs_info->sectorsize);
break; break;
default: default:
pr_cont("(extent %llu has INVALID ref type %d)\n", pr_cont("(extent %llu has INVALID ref type %d)\n",
......
...@@ -1636,6 +1636,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, ...@@ -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); pending->snap = btrfs_get_new_fs_root(fs_info, objectid, pending->anon_dev);
if (IS_ERR(pending->snap)) { if (IS_ERR(pending->snap)) {
ret = PTR_ERR(pending->snap); ret = PTR_ERR(pending->snap);
pending->snap = NULL;
btrfs_abort_transaction(trans, ret); btrfs_abort_transaction(trans, ret);
goto fail; goto fail;
} }
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
*/ */
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/sched/mm.h>
#include <linux/bio.h> #include <linux/bio.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
...@@ -6484,8 +6485,17 @@ static struct btrfs_device *add_missing_dev(struct btrfs_fs_devices *fs_devices, ...@@ -6484,8 +6485,17 @@ static struct btrfs_device *add_missing_dev(struct btrfs_fs_devices *fs_devices,
u64 devid, u8 *dev_uuid) u64 devid, u8 *dev_uuid)
{ {
struct btrfs_device *device; 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); device = btrfs_alloc_device(NULL, &devid, dev_uuid);
memalloc_nofs_restore(nofs_flag);
if (IS_ERR(device)) if (IS_ERR(device))
return device; return device;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment