for-5.4-rc1-tag
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE8rQSAMVO+zA4DBdWxWXV+ddtWDsFAl2SDbMACgkQxWXV+ddt WDsUhw/9HcRsT6SlrwA2R5leHxCR5UMwT2Zmbxpfft37ANF0SC1UINHBfnmquM97 xX6fdRSR9RUjF9DrdLPfLBnJDQ/MnHl1ruIVBFhJm6cJ9TJwf9E0TiJBQt+08JWg vy5hZBWvsPWWRBJ94XPMe4LtakK/isW4Cz5W9AdrC2Siqw69j6eZzms2AnIjyBjA BoKg4se2Ay2rMxLZWXIOj9374PU+N1cnRnqgh77ZxLku5WdCzrDfB5safE7UmoTG /MWJuuIgzOk0iQpQORRtEZDS1dNe5KT9m4xXkUbrZbQROwqnXrT1SVIsuqNAvlPk uaymR1W8nshepzpMlSxVydLv/mKWZNUGnDxOJ23ooow8Yd7ndppXEtFuGwCYqIFc xQqxuTLREvJ9+jpSv11bmDpk/ULRqpV+2PjUqGaWlGwFArJ+qFRLVGYx31eXmDPj t2mrPOcXGzY0pKtIpbkuUGleY/jeI+BNsvD4+QPs+jnp0nmfvH0/Rmp7grGqx2FI rQM8Gn4a5i3nuEDWLp8nN2wcKC3ePwy96Vp2tqfsl6TVTPx4EFzGLkWogHR2yiqI 0LAj8YWFmWuChSv71wYOjX79CppjcbNwOakSwtDjV30jkwoh2f/0D3OwOpua2xe8 75KQMaSB0kesGZz7ZkL1kMqA5m5w7MGZom6XZoBJ+bq2HPLB2jo= =2UM7 -----END PGP SIGNATURE----- Merge tag 'for-5.4-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux Pull btrfs fixes from David Sterba: "A bunch of fixes that accumulated in recent weeks, mostly material for stable. Summary: - fix for regression from 5.3 that prevents to use balance convert with single profile - qgroup fixes: rescan race, accounting leak with multiple writers, potential leak after io failure recovery - fix for use after free in relocation (reported by KASAN) - other error handling fixups" * tag 'for-5.4-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: qgroup: Fix reserved data space leak if we have multiple reserve calls btrfs: qgroup: Fix the wrong target io_tree when freeing reserved data space btrfs: Fix a regression which we can't convert to SINGLE profile btrfs: relocation: fix use-after-free on dead relocation roots Btrfs: fix race setting up and completing qgroup rescan workers Btrfs: fix missing error return if writeback for extent buffer never started btrfs: adjust dirty_metadata_bytes after writeback failure of extent buffer Btrfs: fix selftests failure due to uninitialized i_mode in test inodes
This commit is contained in:
commit
bb48a59135
|
@ -3745,11 +3745,20 @@ err_unlock:
|
||||||
static void set_btree_ioerr(struct page *page)
|
static void set_btree_ioerr(struct page *page)
|
||||||
{
|
{
|
||||||
struct extent_buffer *eb = (struct extent_buffer *)page->private;
|
struct extent_buffer *eb = (struct extent_buffer *)page->private;
|
||||||
|
struct btrfs_fs_info *fs_info;
|
||||||
|
|
||||||
SetPageError(page);
|
SetPageError(page);
|
||||||
if (test_and_set_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags))
|
if (test_and_set_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we error out, we should add back the dirty_metadata_bytes
|
||||||
|
* to make it consistent.
|
||||||
|
*/
|
||||||
|
fs_info = eb->fs_info;
|
||||||
|
percpu_counter_add_batch(&fs_info->dirty_metadata_bytes,
|
||||||
|
eb->len, fs_info->dirty_metadata_batch);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If writeback for a btree extent that doesn't belong to a log tree
|
* If writeback for a btree extent that doesn't belong to a log tree
|
||||||
* failed, increment the counter transaction->eb_write_errors.
|
* failed, increment the counter transaction->eb_write_errors.
|
||||||
|
@ -3986,6 +3995,10 @@ retry:
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
free_extent_buffer(eb);
|
free_extent_buffer(eb);
|
||||||
continue;
|
continue;
|
||||||
|
} else if (ret < 0) {
|
||||||
|
done = 1;
|
||||||
|
free_extent_buffer(eb);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = write_one_eb(eb, wbc, &epd);
|
ret = write_one_eb(eb, wbc, &epd);
|
||||||
|
|
|
@ -3166,9 +3166,6 @@ out:
|
||||||
btrfs_free_path(path);
|
btrfs_free_path(path);
|
||||||
|
|
||||||
mutex_lock(&fs_info->qgroup_rescan_lock);
|
mutex_lock(&fs_info->qgroup_rescan_lock);
|
||||||
if (!btrfs_fs_closing(fs_info))
|
|
||||||
fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_RESCAN;
|
|
||||||
|
|
||||||
if (err > 0 &&
|
if (err > 0 &&
|
||||||
fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT) {
|
fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT) {
|
||||||
fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
|
fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
|
||||||
|
@ -3184,16 +3181,30 @@ out:
|
||||||
trans = btrfs_start_transaction(fs_info->quota_root, 1);
|
trans = btrfs_start_transaction(fs_info->quota_root, 1);
|
||||||
if (IS_ERR(trans)) {
|
if (IS_ERR(trans)) {
|
||||||
err = PTR_ERR(trans);
|
err = PTR_ERR(trans);
|
||||||
|
trans = NULL;
|
||||||
btrfs_err(fs_info,
|
btrfs_err(fs_info,
|
||||||
"fail to start transaction for status update: %d",
|
"fail to start transaction for status update: %d",
|
||||||
err);
|
err);
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
ret = update_qgroup_status_item(trans);
|
|
||||||
if (ret < 0) {
|
mutex_lock(&fs_info->qgroup_rescan_lock);
|
||||||
err = ret;
|
if (!btrfs_fs_closing(fs_info))
|
||||||
btrfs_err(fs_info, "fail to update qgroup status: %d", err);
|
fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_RESCAN;
|
||||||
|
if (trans) {
|
||||||
|
ret = update_qgroup_status_item(trans);
|
||||||
|
if (ret < 0) {
|
||||||
|
err = ret;
|
||||||
|
btrfs_err(fs_info, "fail to update qgroup status: %d",
|
||||||
|
err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
fs_info->qgroup_rescan_running = false;
|
||||||
|
complete_all(&fs_info->qgroup_rescan_completion);
|
||||||
|
mutex_unlock(&fs_info->qgroup_rescan_lock);
|
||||||
|
|
||||||
|
if (!trans)
|
||||||
|
return;
|
||||||
|
|
||||||
btrfs_end_transaction(trans);
|
btrfs_end_transaction(trans);
|
||||||
|
|
||||||
if (btrfs_fs_closing(fs_info)) {
|
if (btrfs_fs_closing(fs_info)) {
|
||||||
|
@ -3204,12 +3215,6 @@ out:
|
||||||
} else {
|
} else {
|
||||||
btrfs_err(fs_info, "qgroup scan failed with %d", err);
|
btrfs_err(fs_info, "qgroup scan failed with %d", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
|
||||||
mutex_lock(&fs_info->qgroup_rescan_lock);
|
|
||||||
fs_info->qgroup_rescan_running = false;
|
|
||||||
mutex_unlock(&fs_info->qgroup_rescan_lock);
|
|
||||||
complete_all(&fs_info->qgroup_rescan_completion);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3437,6 +3442,9 @@ cleanup:
|
||||||
while ((unode = ulist_next(&reserved->range_changed, &uiter)))
|
while ((unode = ulist_next(&reserved->range_changed, &uiter)))
|
||||||
clear_extent_bit(&BTRFS_I(inode)->io_tree, unode->val,
|
clear_extent_bit(&BTRFS_I(inode)->io_tree, unode->val,
|
||||||
unode->aux, EXTENT_QGROUP_RESERVED, 0, 0, NULL);
|
unode->aux, EXTENT_QGROUP_RESERVED, 0, 0, NULL);
|
||||||
|
/* Also free data bytes of already reserved one */
|
||||||
|
btrfs_qgroup_free_refroot(root->fs_info, root->root_key.objectid,
|
||||||
|
orig_reserved, BTRFS_QGROUP_RSV_DATA);
|
||||||
extent_changeset_release(reserved);
|
extent_changeset_release(reserved);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -3481,7 +3489,7 @@ static int qgroup_free_reserved_data(struct inode *inode,
|
||||||
* EXTENT_QGROUP_RESERVED, we won't double free.
|
* EXTENT_QGROUP_RESERVED, we won't double free.
|
||||||
* So not need to rush.
|
* So not need to rush.
|
||||||
*/
|
*/
|
||||||
ret = clear_record_extent_bits(&BTRFS_I(inode)->io_failure_tree,
|
ret = clear_record_extent_bits(&BTRFS_I(inode)->io_tree,
|
||||||
free_start, free_start + free_len - 1,
|
free_start, free_start + free_len - 1,
|
||||||
EXTENT_QGROUP_RESERVED, &changeset);
|
EXTENT_QGROUP_RESERVED, &changeset);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
|
|
@ -1435,6 +1435,13 @@ int btrfs_init_reloc_root(struct btrfs_trans_handle *trans,
|
||||||
int clear_rsv = 0;
|
int clear_rsv = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The subvolume has reloc tree but the swap is finished, no need to
|
||||||
|
* create/update the dead reloc tree
|
||||||
|
*/
|
||||||
|
if (test_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (root->reloc_root) {
|
if (root->reloc_root) {
|
||||||
reloc_root = root->reloc_root;
|
reloc_root = root->reloc_root;
|
||||||
reloc_root->last_trans = trans->transid;
|
reloc_root->last_trans = trans->transid;
|
||||||
|
@ -2187,7 +2194,6 @@ static int clean_dirty_subvols(struct reloc_control *rc)
|
||||||
/* Merged subvolume, cleanup its reloc root */
|
/* Merged subvolume, cleanup its reloc root */
|
||||||
struct btrfs_root *reloc_root = root->reloc_root;
|
struct btrfs_root *reloc_root = root->reloc_root;
|
||||||
|
|
||||||
clear_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state);
|
|
||||||
list_del_init(&root->reloc_dirty_list);
|
list_del_init(&root->reloc_dirty_list);
|
||||||
root->reloc_root = NULL;
|
root->reloc_root = NULL;
|
||||||
if (reloc_root) {
|
if (reloc_root) {
|
||||||
|
@ -2196,6 +2202,7 @@ static int clean_dirty_subvols(struct reloc_control *rc)
|
||||||
if (ret2 < 0 && !ret)
|
if (ret2 < 0 && !ret)
|
||||||
ret = ret2;
|
ret = ret2;
|
||||||
}
|
}
|
||||||
|
clear_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state);
|
||||||
btrfs_put_fs_root(root);
|
btrfs_put_fs_root(root);
|
||||||
} else {
|
} else {
|
||||||
/* Orphan reloc tree, just clean it up */
|
/* Orphan reloc tree, just clean it up */
|
||||||
|
|
|
@ -52,7 +52,13 @@ static struct file_system_type test_type = {
|
||||||
|
|
||||||
struct inode *btrfs_new_test_inode(void)
|
struct inode *btrfs_new_test_inode(void)
|
||||||
{
|
{
|
||||||
return new_inode(test_mnt->mnt_sb);
|
struct inode *inode;
|
||||||
|
|
||||||
|
inode = new_inode(test_mnt->mnt_sb);
|
||||||
|
if (inode)
|
||||||
|
inode_init_owner(inode, NULL, S_IFREG);
|
||||||
|
|
||||||
|
return inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int btrfs_init_test_fs(void)
|
static int btrfs_init_test_fs(void)
|
||||||
|
|
|
@ -4063,7 +4063,13 @@ int btrfs_balance(struct btrfs_fs_info *fs_info,
|
||||||
}
|
}
|
||||||
|
|
||||||
num_devices = btrfs_num_devices(fs_info);
|
num_devices = btrfs_num_devices(fs_info);
|
||||||
allowed = 0;
|
|
||||||
|
/*
|
||||||
|
* SINGLE profile on-disk has no profile bit, but in-memory we have a
|
||||||
|
* special bit for it, to make it easier to distinguish. Thus we need
|
||||||
|
* to set it manually, or balance would refuse the profile.
|
||||||
|
*/
|
||||||
|
allowed = BTRFS_AVAIL_ALLOC_BIT_SINGLE;
|
||||||
for (i = 0; i < ARRAY_SIZE(btrfs_raid_array); i++)
|
for (i = 0; i < ARRAY_SIZE(btrfs_raid_array); i++)
|
||||||
if (num_devices >= btrfs_raid_array[i].devs_min)
|
if (num_devices >= btrfs_raid_array[i].devs_min)
|
||||||
allowed |= btrfs_raid_array[i].bg_flag;
|
allowed |= btrfs_raid_array[i].bg_flag;
|
||||||
|
|
Loading…
Reference in New Issue