Merge tag 'for-6.4-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
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
This commit is contained in:
@ -996,13 +996,18 @@ int btrfs_global_root_insert(struct btrfs_root *root)
|
|||||||
{
|
{
|
||||||
struct btrfs_fs_info *fs_info = root->fs_info;
|
struct btrfs_fs_info *fs_info = root->fs_info;
|
||||||
struct rb_node *tmp;
|
struct rb_node *tmp;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
write_lock(&fs_info->global_root_lock);
|
write_lock(&fs_info->global_root_lock);
|
||||||
tmp = rb_find_add(&root->rb_node, &fs_info->global_root_tree, global_root_cmp);
|
tmp = rb_find_add(&root->rb_node, &fs_info->global_root_tree, global_root_cmp);
|
||||||
write_unlock(&fs_info->global_root_lock);
|
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)
|
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 */
|
/* We can't trust the free space cache either */
|
||||||
btrfs_set_opt(fs_info->mount_opt, CLEAR_CACHE);
|
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);
|
ret = read_backup_root(fs_info, i);
|
||||||
backup_index = ret;
|
backup_index = ret;
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@ -1864,7 +1864,7 @@ static int can_nocow_file_extent(struct btrfs_path *path,
|
|||||||
|
|
||||||
ret = btrfs_cross_ref_exist(root, btrfs_ino(inode),
|
ret = btrfs_cross_ref_exist(root, btrfs_ino(inode),
|
||||||
key->offset - args->extent_offset,
|
key->offset - args->extent_offset,
|
||||||
args->disk_bytenr, false, path);
|
args->disk_bytenr, args->strict, path);
|
||||||
WARN_ON_ONCE(ret > 0 && is_freespace_inode);
|
WARN_ON_ONCE(ret > 0 && is_freespace_inode);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
goto out;
|
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,
|
static int btrfs_get_blocks_direct_write(struct extent_map **map,
|
||||||
struct inode *inode,
|
struct inode *inode,
|
||||||
struct btrfs_dio_data *dio_data,
|
struct btrfs_dio_data *dio_data,
|
||||||
u64 start, u64 len,
|
u64 start, u64 *lenp,
|
||||||
unsigned int iomap_flags)
|
unsigned int iomap_flags)
|
||||||
{
|
{
|
||||||
const bool nowait = (iomap_flags & IOMAP_NOWAIT);
|
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;
|
struct btrfs_block_group *bg;
|
||||||
bool can_nocow = false;
|
bool can_nocow = false;
|
||||||
bool space_reserved = false;
|
bool space_reserved = false;
|
||||||
|
u64 len = *lenp;
|
||||||
u64 prev_len;
|
u64 prev_len;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
@ -7345,15 +7346,19 @@ static int btrfs_get_blocks_direct_write(struct extent_map **map,
|
|||||||
free_extent_map(em);
|
free_extent_map(em);
|
||||||
*map = NULL;
|
*map = NULL;
|
||||||
|
|
||||||
if (nowait)
|
if (nowait) {
|
||||||
return -EAGAIN;
|
ret = -EAGAIN;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we could not allocate data space before locking the file
|
* 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.
|
* range and we can't do a NOCOW write, then we have to fail.
|
||||||
*/
|
*/
|
||||||
if (!dio_data->data_space_reserved)
|
if (!dio_data->data_space_reserved) {
|
||||||
return -ENOSPC;
|
ret = -ENOSPC;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have to COW and we have already reserved data space before,
|
* We have to COW and we have already reserved data space before,
|
||||||
@ -7394,6 +7399,7 @@ out:
|
|||||||
btrfs_delalloc_release_extents(BTRFS_I(inode), len);
|
btrfs_delalloc_release_extents(BTRFS_I(inode), len);
|
||||||
btrfs_delalloc_release_metadata(BTRFS_I(inode), len, true);
|
btrfs_delalloc_release_metadata(BTRFS_I(inode), len, true);
|
||||||
}
|
}
|
||||||
|
*lenp = len;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7570,7 +7576,7 @@ static int btrfs_dio_iomap_begin(struct inode *inode, loff_t start,
|
|||||||
|
|
||||||
if (write) {
|
if (write) {
|
||||||
ret = btrfs_get_blocks_direct_write(&em, inode, dio_data,
|
ret = btrfs_get_blocks_direct_write(&em, inode, dio_data,
|
||||||
start, len, flags);
|
start, &len, flags);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto unlock_err;
|
goto unlock_err;
|
||||||
unlock_extents = true;
|
unlock_extents = true;
|
||||||
|
@ -2266,7 +2266,7 @@ next:
|
|||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
ret2 = flush_scrub_stripes(sctx);
|
ret2 = flush_scrub_stripes(sctx);
|
||||||
if (!ret2)
|
if (!ret)
|
||||||
ret = ret2;
|
ret = ret2;
|
||||||
if (sctx->raid56_data_stripes) {
|
if (sctx->raid56_data_stripes) {
|
||||||
for (int i = 0; i < nr_data_stripes(map); i++)
|
for (int i = 0; i < nr_data_stripes(map); i++)
|
||||||
|
Reference in New Issue
Block a user