Commit c05d51c7 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull btrfs fixes from David Sterba:
 "A few more fixes for a late rc:

   - fix lockdep complaint on 32bit arches and also remove an unsafe
     memory use due to device vs filesystem lifetime

   - two fixes for free space tree:

      * race during log replay and cache rebuild, now more likely to
        happen due to changes in this dev cycle

      * possible free space tree corruption with online conversion
        during initial tree population"

* tag 'for-5.11-rc5-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: fix log replay failure due to race with space cache rebuild
  btrfs: fix lockdep warning due to seqcount_mutex on 32bit arch
  btrfs: fix possible free space tree corruption with online conversion
parents 2ba1c4d1 9ad6d91f
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -673,7 +673,15 @@ static noinline void caching_thread(struct btrfs_work *work)
		wake_up(&caching_ctl->wait);
	}

	if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE))
	/*
	 * If we are in the transaction that populated the free space tree we
	 * can't actually cache from the free space tree as our commit root and
	 * real root are the same, so we could change the contents of the blocks
	 * while caching.  Instead do the slow caching in this case, and after
	 * the transaction has committed we will be safe.
	 */
	if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE) &&
	    !(test_bit(BTRFS_FS_FREE_SPACE_TREE_UNTRUSTED, &fs_info->flags)))
		ret = load_free_space_tree(caching_ctl);
	else
		ret = load_extent_tree_free(caching_ctl);
+3 −0
Original line number Diff line number Diff line
@@ -563,6 +563,9 @@ enum {

	/* Indicate that we need to cleanup space cache v1 */
	BTRFS_FS_CLEANUP_SPACE_CACHE_V1,

	/* Indicate that we can't trust the free space tree for caching yet */
	BTRFS_FS_FREE_SPACE_TREE_UNTRUSTED,
};

/*
+18 −43
Original line number Diff line number Diff line
@@ -2602,8 +2602,6 @@ int btrfs_pin_extent_for_log_replay(struct btrfs_trans_handle *trans,
	struct btrfs_block_group *cache;
	int ret;

	btrfs_add_excluded_extent(trans->fs_info, bytenr, num_bytes);

	cache = btrfs_lookup_block_group(trans->fs_info, bytenr);
	if (!cache)
		return -EINVAL;
@@ -2615,11 +2613,19 @@ int btrfs_pin_extent_for_log_replay(struct btrfs_trans_handle *trans,
	 * the pinned extents.
	 */
	btrfs_cache_block_group(cache, 1);
	/*
	 * Make sure we wait until the cache is completely built in case it is
	 * missing or is invalid and therefore needs to be rebuilt.
	 */
	ret = btrfs_wait_block_group_cache_done(cache);
	if (ret)
		goto out;

	pin_down_extent(trans, cache, bytenr, num_bytes, 0);

	/* remove us from the free space cache (if we're there at all) */
	ret = btrfs_remove_free_space(cache, bytenr, num_bytes);
out:
	btrfs_put_block_group(cache);
	return ret;
}
@@ -2629,50 +2635,22 @@ static int __exclude_logged_extent(struct btrfs_fs_info *fs_info,
{
	int ret;
	struct btrfs_block_group *block_group;
	struct btrfs_caching_control *caching_ctl;

	block_group = btrfs_lookup_block_group(fs_info, start);
	if (!block_group)
		return -EINVAL;

	btrfs_cache_block_group(block_group, 0);
	caching_ctl = btrfs_get_caching_control(block_group);

	if (!caching_ctl) {
		/* Logic error */
		BUG_ON(!btrfs_block_group_done(block_group));
		ret = btrfs_remove_free_space(block_group, start, num_bytes);
	} else {
	btrfs_cache_block_group(block_group, 1);
	/*
		 * We must wait for v1 caching to finish, otherwise we may not
		 * remove our space.
	 * Make sure we wait until the cache is completely built in case it is
	 * missing or is invalid and therefore needs to be rebuilt.
	 */
		btrfs_wait_space_cache_v1_finished(block_group, caching_ctl);
		mutex_lock(&caching_ctl->mutex);

		if (start >= caching_ctl->progress) {
			ret = btrfs_add_excluded_extent(fs_info, start,
							num_bytes);
		} else if (start + num_bytes <= caching_ctl->progress) {
			ret = btrfs_remove_free_space(block_group,
						      start, num_bytes);
		} else {
			num_bytes = caching_ctl->progress - start;
			ret = btrfs_remove_free_space(block_group,
						      start, num_bytes);
	ret = btrfs_wait_block_group_cache_done(block_group);
	if (ret)
				goto out_lock;
		goto out;

			num_bytes = (start + num_bytes) -
				caching_ctl->progress;
			start = caching_ctl->progress;
			ret = btrfs_add_excluded_extent(fs_info, start,
							num_bytes);
		}
out_lock:
		mutex_unlock(&caching_ctl->mutex);
		btrfs_put_caching_control(caching_ctl);
	}
	ret = btrfs_remove_free_space(block_group, start, num_bytes);
out:
	btrfs_put_block_group(block_group);
	return ret;
}
@@ -2863,9 +2841,6 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans)
			mutex_unlock(&fs_info->unused_bg_unpin_mutex);
			break;
		}
		if (test_bit(BTRFS_FS_LOG_RECOVERING, &fs_info->flags))
			clear_extent_bits(&fs_info->excluded_extents, start,
					  end, EXTENT_UPTODATE);

		if (btrfs_test_opt(fs_info, DISCARD_SYNC))
			ret = btrfs_discard_extent(fs_info, start,
+9 −1
Original line number Diff line number Diff line
@@ -1150,6 +1150,7 @@ int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info)
		return PTR_ERR(trans);

	set_bit(BTRFS_FS_CREATING_FREE_SPACE_TREE, &fs_info->flags);
	set_bit(BTRFS_FS_FREE_SPACE_TREE_UNTRUSTED, &fs_info->flags);
	free_space_root = btrfs_create_tree(trans,
					    BTRFS_FREE_SPACE_TREE_OBJECTID);
	if (IS_ERR(free_space_root)) {
@@ -1171,11 +1172,18 @@ int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info)
	btrfs_set_fs_compat_ro(fs_info, FREE_SPACE_TREE);
	btrfs_set_fs_compat_ro(fs_info, FREE_SPACE_TREE_VALID);
	clear_bit(BTRFS_FS_CREATING_FREE_SPACE_TREE, &fs_info->flags);
	ret = btrfs_commit_transaction(trans);

	return btrfs_commit_transaction(trans);
	/*
	 * Now that we've committed the transaction any reading of our commit
	 * root will be safe, so we can cache from the free space tree now.
	 */
	clear_bit(BTRFS_FS_FREE_SPACE_TREE_UNTRUSTED, &fs_info->flags);
	return ret;

abort:
	clear_bit(BTRFS_FS_CREATING_FREE_SPACE_TREE, &fs_info->flags);
	clear_bit(BTRFS_FS_FREE_SPACE_TREE_UNTRUSTED, &fs_info->flags);
	btrfs_abort_transaction(trans, ret);
	btrfs_end_transaction(trans);
	return ret;
+1 −1
Original line number Diff line number Diff line
@@ -433,7 +433,7 @@ static struct btrfs_device *__alloc_device(struct btrfs_fs_info *fs_info)

	atomic_set(&dev->reada_in_flight, 0);
	atomic_set(&dev->dev_stats_ccnt, 0);
	btrfs_device_data_ordered_init(dev, fs_info);
	btrfs_device_data_ordered_init(dev);
	INIT_RADIX_TREE(&dev->reada_zones, GFP_NOFS & ~__GFP_DIRECT_RECLAIM);
	INIT_RADIX_TREE(&dev->reada_extents, GFP_NOFS & ~__GFP_DIRECT_RECLAIM);
	extent_io_tree_init(fs_info, &dev->alloc_state,
Loading