Commit 2187f215 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull btrfs fixes from David Sterba:
 "A mix of regression fixes and regular fixes for stable trees:

   - fix swapped error messages for qgroup enable/rescan

   - fixes for NO_HOLES feature with clone range

   - fix deadlock between iget/srcu lock/synchronize srcu while freeing
     an inode

   - fix double lock on subvolume cross-rename

   - tree log fixes
      * fix missing data checksums after replaying a log tree
      * also teach tree-checker about this problem
      * skip log replay on orphaned roots

   - fix maximum devices constraints for RAID1C -3 and -4

   - send: don't print warning on read-only mount regarding orphan
     cleanup

   - error handling fixes"

* tag 'for-5.5-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: send: remove WARN_ON for readonly mount
  btrfs: do not leak reloc root if we fail to read the fs root
  btrfs: skip log replay on orphaned roots
  btrfs: handle ENOENT in btrfs_uuid_tree_iterate
  btrfs: abort transaction after failed inode updates in create_subvol
  Btrfs: fix hole extent items with a zero size after range cloning
  Btrfs: fix removal logic of the tree mod log that leads to use-after-free issues
  Btrfs: make tree checker detect checksum items with overlapping ranges
  Btrfs: fix missing data checksums after replaying a log tree
  btrfs: return error pointer from alloc_test_extent_buffer
  btrfs: fix devs_max constraints for raid1c3 and raid1c4
  btrfs: tree-checker: Fix error format string for size_t
  btrfs: don't double lock the subvol_sem for rename exchange
  btrfs: handle error in btrfs_cache_block_group
  btrfs: do not call synchronize_srcu() in inode_tree_del
  Btrfs: fix cloning range with a hole when using the NO_HOLES feature
  btrfs: Fix error messages in qgroup_rescan_init
parents 2d3145f8 fbd54297
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -379,7 +379,7 @@ void btrfs_put_tree_mod_seq(struct btrfs_fs_info *fs_info,
	for (node = rb_first(tm_root); node; node = next) {
		next = rb_next(node);
		tm = rb_entry(node, struct tree_mod_elem, node);
		if (tm->seq > min_seq)
		if (tm->seq >= min_seq)
			continue;
		rb_erase(node, tm_root);
		kfree(tm);
+1 −1
Original line number Diff line number Diff line
@@ -2787,7 +2787,7 @@ struct btrfs_inode_extref *btrfs_find_name_in_ext_backref(
/* file-item.c */
struct btrfs_dio_private;
int btrfs_del_csums(struct btrfs_trans_handle *trans,
		    struct btrfs_fs_info *fs_info, u64 bytenr, u64 len);
		    struct btrfs_root *root, u64 bytenr, u64 len);
blk_status_t btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio,
				   u8 *dst);
blk_status_t btrfs_lookup_bio_sums_dio(struct inode *inode, struct bio *bio,
+22 −5
Original line number Diff line number Diff line
@@ -1869,8 +1869,8 @@ static int cleanup_ref_head(struct btrfs_trans_handle *trans,
		btrfs_pin_extent(fs_info, head->bytenr,
				 head->num_bytes, 1);
		if (head->is_data) {
			ret = btrfs_del_csums(trans, fs_info, head->bytenr,
					      head->num_bytes);
			ret = btrfs_del_csums(trans, fs_info->csum_root,
					      head->bytenr, head->num_bytes);
		}
	}

@@ -3175,7 +3175,8 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
		btrfs_release_path(path);

		if (is_data) {
			ret = btrfs_del_csums(trans, info, bytenr, num_bytes);
			ret = btrfs_del_csums(trans, info->csum_root, bytenr,
					      num_bytes);
			if (ret) {
				btrfs_abort_transaction(trans, ret);
				goto out;
@@ -3799,6 +3800,7 @@ static noinline int find_free_extent(struct btrfs_fs_info *fs_info,
				u64 flags, int delalloc)
{
	int ret = 0;
	int cache_block_group_error = 0;
	struct btrfs_free_cluster *last_ptr = NULL;
	struct btrfs_block_group *block_group = NULL;
	struct find_free_extent_ctl ffe_ctl = {0};
@@ -3958,7 +3960,20 @@ have_block_group:
		if (unlikely(!ffe_ctl.cached)) {
			ffe_ctl.have_caching_bg = true;
			ret = btrfs_cache_block_group(block_group, 0);
			BUG_ON(ret < 0);

			/*
			 * If we get ENOMEM here or something else we want to
			 * try other block groups, because it may not be fatal.
			 * However if we can't find anything else we need to
			 * save our return here so that we return the actual
			 * error that caused problems, not ENOSPC.
			 */
			if (ret < 0) {
				if (!cache_block_group_error)
					cache_block_group_error = ret;
				ret = 0;
				goto loop;
			}
			ret = 0;
		}

@@ -4045,7 +4060,7 @@ loop:
	if (ret > 0)
		goto search;

	if (ret == -ENOSPC) {
	if (ret == -ENOSPC && !cache_block_group_error) {
		/*
		 * Use ffe_ctl->total_free_space as fallback if we can't find
		 * any contiguous hole.
@@ -4056,6 +4071,8 @@ loop:
		space_info->max_extent_size = ffe_ctl.max_extent_size;
		spin_unlock(&space_info->lock);
		ins->offset = ffe_ctl.max_extent_size;
	} else if (ret == -ENOSPC) {
		ret = cache_block_group_error;
	}
	return ret;
}
+4 −2
Original line number Diff line number Diff line
@@ -5074,12 +5074,14 @@ struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info,
		return eb;
	eb = alloc_dummy_extent_buffer(fs_info, start);
	if (!eb)
		return NULL;
		return ERR_PTR(-ENOMEM);
	eb->fs_info = fs_info;
again:
	ret = radix_tree_preload(GFP_NOFS);
	if (ret)
	if (ret) {
		exists = ERR_PTR(ret);
		goto free_eb;
	}
	spin_lock(&fs_info->buffer_lock);
	ret = radix_tree_insert(&fs_info->buffer_radix,
				start >> PAGE_SHIFT, eb);
+5 −2
Original line number Diff line number Diff line
@@ -590,9 +590,9 @@ static noinline void truncate_one_csum(struct btrfs_fs_info *fs_info,
 * range of bytes.
 */
int btrfs_del_csums(struct btrfs_trans_handle *trans,
		    struct btrfs_fs_info *fs_info, u64 bytenr, u64 len)
		    struct btrfs_root *root, u64 bytenr, u64 len)
{
	struct btrfs_root *root = fs_info->csum_root;
	struct btrfs_fs_info *fs_info = trans->fs_info;
	struct btrfs_path *path;
	struct btrfs_key key;
	u64 end_byte = bytenr + len;
@@ -602,6 +602,9 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans,
	u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
	int blocksize_bits = fs_info->sb->s_blocksize_bits;

	ASSERT(root == fs_info->csum_root ||
	       root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID);

	path = btrfs_alloc_path();
	if (!path)
		return -ENOMEM;
Loading