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

Commit e5e03ad9 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull btrfs fixes from David Sterba:
 "We've accumulated some fixes during the last week, some of them were
  in the works for a longer time but there are some newer ones too.

  Most of the fixes have a reproducer and fix user visible problems,
  also candidates for stable kernels. They IMHO qualify for a late rc,
  though I did not expect that many"

* tag 'for-4.17-rc5-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: fix crash when trying to resume balance without the resume flag
  btrfs: Fix delalloc inodes invalidation during transaction abort
  btrfs: Split btrfs_del_delalloc_inode into 2 functions
  btrfs: fix reading stale metadata blocks after degraded raid1 mounts
  btrfs: property: Set incompat flag if lzo/zstd compression is set
  Btrfs: fix duplicate extents after fsync of file with prealloc extents
  Btrfs: fix xattr loss after power failure
  Btrfs: send, fix invalid access to commit roots due to concurrent snapshotting
parents 132ce5d4 02ee654d
Loading
Loading
Loading
Loading
+17 −5
Original line number Diff line number Diff line
@@ -2436,10 +2436,8 @@ read_block_for_search(struct btrfs_root *root, struct btrfs_path *p,
	if (p->reada != READA_NONE)
		reada_for_search(fs_info, p, level, slot, key->objectid);

	btrfs_release_path(p);

	ret = -EAGAIN;
	tmp = read_tree_block(fs_info, blocknr, 0, parent_level - 1,
	tmp = read_tree_block(fs_info, blocknr, gen, parent_level - 1,
			      &first_key);
	if (!IS_ERR(tmp)) {
		/*
@@ -2454,6 +2452,8 @@ read_block_for_search(struct btrfs_root *root, struct btrfs_path *p,
	} else {
		ret = PTR_ERR(tmp);
	}

	btrfs_release_path(p);
	return ret;
}

@@ -5414,12 +5414,24 @@ int btrfs_compare_trees(struct btrfs_root *left_root,
	down_read(&fs_info->commit_root_sem);
	left_level = btrfs_header_level(left_root->commit_root);
	left_root_level = left_level;
	left_path->nodes[left_level] = left_root->commit_root;
	left_path->nodes[left_level] =
			btrfs_clone_extent_buffer(left_root->commit_root);
	if (!left_path->nodes[left_level]) {
		up_read(&fs_info->commit_root_sem);
		ret = -ENOMEM;
		goto out;
	}
	extent_buffer_get(left_path->nodes[left_level]);

	right_level = btrfs_header_level(right_root->commit_root);
	right_root_level = right_level;
	right_path->nodes[right_level] = right_root->commit_root;
	right_path->nodes[right_level] =
			btrfs_clone_extent_buffer(right_root->commit_root);
	if (!right_path->nodes[right_level]) {
		up_read(&fs_info->commit_root_sem);
		ret = -ENOMEM;
		goto out;
	}
	extent_buffer_get(right_path->nodes[right_level]);
	up_read(&fs_info->commit_root_sem);

+2 −0
Original line number Diff line number Diff line
@@ -3182,6 +3182,8 @@ noinline int can_nocow_extent(struct inode *inode, u64 offset, u64 *len,
			      u64 *orig_start, u64 *orig_block_len,
			      u64 *ram_bytes);

void __btrfs_del_delalloc_inode(struct btrfs_root *root,
				struct btrfs_inode *inode);
struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry);
int btrfs_set_inode_index(struct btrfs_inode *dir, u64 *index);
int btrfs_unlink_inode(struct btrfs_trans_handle *trans,
+15 −11
Original line number Diff line number Diff line
@@ -3818,6 +3818,7 @@ void close_ctree(struct btrfs_fs_info *fs_info)
	set_bit(BTRFS_FS_CLOSING_DONE, &fs_info->flags);

	btrfs_free_qgroup_config(fs_info);
	ASSERT(list_empty(&fs_info->delalloc_roots));

	if (percpu_counter_sum(&fs_info->delalloc_bytes)) {
		btrfs_info(fs_info, "at unmount delalloc count %lld",
@@ -4125,15 +4126,15 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info)

static void btrfs_error_commit_super(struct btrfs_fs_info *fs_info)
{
	/* cleanup FS via transaction */
	btrfs_cleanup_transaction(fs_info);

	mutex_lock(&fs_info->cleaner_mutex);
	btrfs_run_delayed_iputs(fs_info);
	mutex_unlock(&fs_info->cleaner_mutex);

	down_write(&fs_info->cleanup_work_sem);
	up_write(&fs_info->cleanup_work_sem);

	/* cleanup FS via transaction */
	btrfs_cleanup_transaction(fs_info);
}

static void btrfs_destroy_ordered_extents(struct btrfs_root *root)
@@ -4258,19 +4259,23 @@ static void btrfs_destroy_delalloc_inodes(struct btrfs_root *root)
	list_splice_init(&root->delalloc_inodes, &splice);

	while (!list_empty(&splice)) {
		struct inode *inode = NULL;
		btrfs_inode = list_first_entry(&splice, struct btrfs_inode,
					       delalloc_inodes);

		list_del_init(&btrfs_inode->delalloc_inodes);
		clear_bit(BTRFS_INODE_IN_DELALLOC_LIST,
			  &btrfs_inode->runtime_flags);
		__btrfs_del_delalloc_inode(root, btrfs_inode);
		spin_unlock(&root->delalloc_lock);

		btrfs_invalidate_inodes(btrfs_inode->root);

		/*
		 * Make sure we get a live inode and that it'll not disappear
		 * meanwhile.
		 */
		inode = igrab(&btrfs_inode->vfs_inode);
		if (inode) {
			invalidate_inode_pages2(inode->i_mapping);
			iput(inode);
		}
		spin_lock(&root->delalloc_lock);
	}

	spin_unlock(&root->delalloc_lock);
}

@@ -4286,7 +4291,6 @@ static void btrfs_destroy_all_delalloc_inodes(struct btrfs_fs_info *fs_info)
	while (!list_empty(&splice)) {
		root = list_first_entry(&splice, struct btrfs_root,
					 delalloc_root);
		list_del_init(&root->delalloc_root);
		root = btrfs_grab_fs_root(root);
		BUG_ON(!root);
		spin_unlock(&fs_info->delalloc_root_lock);
+10 −3
Original line number Diff line number Diff line
@@ -1742,12 +1742,12 @@ static void btrfs_add_delalloc_inodes(struct btrfs_root *root,
	spin_unlock(&root->delalloc_lock);
}

static void btrfs_del_delalloc_inode(struct btrfs_root *root,

void __btrfs_del_delalloc_inode(struct btrfs_root *root,
				struct btrfs_inode *inode)
{
	struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb);

	spin_lock(&root->delalloc_lock);
	if (!list_empty(&inode->delalloc_inodes)) {
		list_del_init(&inode->delalloc_inodes);
		clear_bit(BTRFS_INODE_IN_DELALLOC_LIST,
@@ -1760,6 +1760,13 @@ static void btrfs_del_delalloc_inode(struct btrfs_root *root,
			spin_unlock(&fs_info->delalloc_root_lock);
		}
	}
}

static void btrfs_del_delalloc_inode(struct btrfs_root *root,
				     struct btrfs_inode *inode)
{
	spin_lock(&root->delalloc_lock);
	__btrfs_del_delalloc_inode(root, inode);
	spin_unlock(&root->delalloc_lock);
}

+8 −4
Original line number Diff line number Diff line
@@ -380,6 +380,7 @@ static int prop_compression_apply(struct inode *inode,
				  const char *value,
				  size_t len)
{
	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
	int type;

	if (len == 0) {
@@ -390,14 +391,17 @@ static int prop_compression_apply(struct inode *inode,
		return 0;
	}

	if (!strncmp("lzo", value, 3))
	if (!strncmp("lzo", value, 3)) {
		type = BTRFS_COMPRESS_LZO;
	else if (!strncmp("zlib", value, 4))
		btrfs_set_fs_incompat(fs_info, COMPRESS_LZO);
	} else if (!strncmp("zlib", value, 4)) {
		type = BTRFS_COMPRESS_ZLIB;
	else if (!strncmp("zstd", value, len))
	} else if (!strncmp("zstd", value, len)) {
		type = BTRFS_COMPRESS_ZSTD;
	else
		btrfs_set_fs_incompat(fs_info, COMPRESS_ZSTD);
	} else {
		return -EINVAL;
	}

	BTRFS_I(inode)->flags &= ~BTRFS_INODE_NOCOMPRESS;
	BTRFS_I(inode)->flags |= BTRFS_INODE_COMPRESS;
Loading