Commit 4973ca29 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull btrfs fixes from David Sterba:
 "Two fixes for NOCOW files, a regression fix in scrub and an assertion
  fix:

   - NOCOW fixes:
      - keep length of iomap direct io request in case of a failure
      - properly pass mode of extent reference checking, this can break
        some cases for swapfile

   - fix error value confusion when scrubbing a stripe

   - convert assertion to a proper error handling when loading global
     roots, reported by syzbot"

* tag 'for-6.4-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: scrub: fix a return value overwrite in scrub_stripe()
  btrfs: do not ASSERT() on duplicated global roots
  btrfs: can_nocow_file_extent should pass down args->strict from callers
  btrfs: fix iomap_begin length for nocow writes
parents b9c1133a b50f2d04
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -996,13 +996,18 @@ int btrfs_global_root_insert(struct btrfs_root *root)
{
	struct btrfs_fs_info *fs_info = root->fs_info;
	struct rb_node *tmp;
	int ret = 0;

	write_lock(&fs_info->global_root_lock);
	tmp = rb_find_add(&root->rb_node, &fs_info->global_root_tree, global_root_cmp);
	write_unlock(&fs_info->global_root_lock);
	ASSERT(!tmp);

	return tmp ? -EEXIST : 0;
	if (tmp) {
		ret = -EEXIST;
		btrfs_warn(fs_info, "global root %llu %llu already exists",
				root->root_key.objectid, root->root_key.offset);
	}
	return ret;
}

void btrfs_global_root_delete(struct btrfs_root *root)
@@ -2842,6 +2847,7 @@ static int __cold init_tree_roots(struct btrfs_fs_info *fs_info)
			/* We can't trust the free space cache either */
			btrfs_set_opt(fs_info->mount_opt, CLEAR_CACHE);

			btrfs_warn(fs_info, "try to load backup roots slot %d", i);
			ret = read_backup_root(fs_info, i);
			backup_index = ret;
			if (ret < 0)
+13 −7
Original line number Diff line number Diff line
@@ -1864,7 +1864,7 @@ static int can_nocow_file_extent(struct btrfs_path *path,

	ret = btrfs_cross_ref_exist(root, btrfs_ino(inode),
				    key->offset - args->extent_offset,
				    args->disk_bytenr, false, path);
				    args->disk_bytenr, args->strict, path);
	WARN_ON_ONCE(ret > 0 && is_freespace_inode);
	if (ret != 0)
		goto out;
@@ -7264,7 +7264,7 @@ static struct extent_map *create_io_em(struct btrfs_inode *inode, u64 start,
static int btrfs_get_blocks_direct_write(struct extent_map **map,
					 struct inode *inode,
					 struct btrfs_dio_data *dio_data,
					 u64 start, u64 len,
					 u64 start, u64 *lenp,
					 unsigned int iomap_flags)
{
	const bool nowait = (iomap_flags & IOMAP_NOWAIT);
@@ -7275,6 +7275,7 @@ static int btrfs_get_blocks_direct_write(struct extent_map **map,
	struct btrfs_block_group *bg;
	bool can_nocow = false;
	bool space_reserved = false;
	u64 len = *lenp;
	u64 prev_len;
	int ret = 0;

@@ -7345,15 +7346,19 @@ static int btrfs_get_blocks_direct_write(struct extent_map **map,
		free_extent_map(em);
		*map = NULL;

		if (nowait)
			return -EAGAIN;
		if (nowait) {
			ret = -EAGAIN;
			goto out;
		}

		/*
		 * If we could not allocate data space before locking the file
		 * range and we can't do a NOCOW write, then we have to fail.
		 */
		if (!dio_data->data_space_reserved)
			return -ENOSPC;
		if (!dio_data->data_space_reserved) {
			ret = -ENOSPC;
			goto out;
		}

		/*
		 * We have to COW and we have already reserved data space before,
@@ -7394,6 +7399,7 @@ static int btrfs_get_blocks_direct_write(struct extent_map **map,
		btrfs_delalloc_release_extents(BTRFS_I(inode), len);
		btrfs_delalloc_release_metadata(BTRFS_I(inode), len, true);
	}
	*lenp = len;
	return ret;
}

@@ -7570,7 +7576,7 @@ static int btrfs_dio_iomap_begin(struct inode *inode, loff_t start,

	if (write) {
		ret = btrfs_get_blocks_direct_write(&em, inode, dio_data,
						    start, len, flags);
						    start, &len, flags);
		if (ret < 0)
			goto unlock_err;
		unlock_extents = true;
+1 −1
Original line number Diff line number Diff line
@@ -2266,7 +2266,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
	}
out:
	ret2 = flush_scrub_stripes(sctx);
	if (!ret2)
	if (!ret)
		ret = ret2;
	if (sctx->raid56_data_stripes) {
		for (int i = 0; i < nr_data_stripes(map); i++)