for-6.9-rc2-tag
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE8rQSAMVO+zA4DBdWxWXV+ddtWDsFAmYQIdIACgkQxWXV+ddt WDvjmw/+KahIHfFt17cM5uZpiETcL9v44uT0Y69r0bMpw8Vy/cmE+rmGfyERr8YN v68U/hpWHD2mYhxL01EHut2X/MRA4zmAcWUKVu1vk0d/9Vp/01wPJfKyvX6q388/ dFtPtzqXxj0uIwO5lRIk+dJuvShtfCps2rx/zcBUoaQYljIDNfhrWscfV4nIzqlR BF7GX3b22rlw8q1dXAXWW+zTk3tey8Jxj+jmShyoPxcGMDK4jmNyaFu1WSIFfSdc ns5Kii7/4tIBqpqPCr/FMGXQjdEZGw9ZTiAO4nUjtyoCTO3l/jMVYoo7llJR9dtv Fgtej0MLlAapX2mJ65xOBO6OvCIM8VwrY+DfIDeWxtDONmrGxBUIMTJIjSq3oGEi Mh0CbnpISGj9zQlR4raOavtgxmbdXnhdvLcp2Uv+VcJnEyCtHMmVLx9yNMKqjHje oJHtuJiEeqlB66xZEYx3qA8SIdaJGhB/HluU9Vyg67AJTJUcCzuxZlqaC+oSOxfj GYgY66BHD+ZKRKUFw7EylohnhvsMcmFhMSeBLzMuSaqEig4dmv4cFenad06up6c+ c0obH8oKsaA05gS3sMshmkNtBm8ms1OP2rWebjQWmmXhCOWLPqcGs5AxYeqvRdzx eqFNKhRw+JH1mFmhEtY/Y+4OX6eTlluSxoKxZYWfAX1xvlr94U4= =XtPw -----END PGP SIGNATURE----- Merge tag 'for-6.9-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux Pull btrfs fixes from David Sterba: "Several fixes to qgroups that have been recently identified by test generic/475: - fix prealloc reserve leak in subvolume operations - various other fixes in reservation setup, conversion or cleanup" * tag 'for-6.9-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: always clear PERTRANS metadata during commit btrfs: make btrfs_clear_delalloc_extent() free delalloc reserve btrfs: qgroup: convert PREALLOC to PERTRANS after record_root_in_trans btrfs: record delayed inode root in transaction btrfs: qgroup: fix qgroup prealloc rsv leak in subvolume operations btrfs: qgroup: correctly model root qgroup rsv in convert
This commit is contained in:
commit
20cb38a7af
|
@ -1133,6 +1133,9 @@ __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans,
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
ret = btrfs_record_root_in_trans(trans, node->root);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
ret = btrfs_update_delayed_inode(trans, node->root, path, node);
|
ret = btrfs_update_delayed_inode(trans, node->root, path, node);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2533,7 +2533,7 @@ void btrfs_clear_delalloc_extent(struct btrfs_inode *inode,
|
||||||
*/
|
*/
|
||||||
if (bits & EXTENT_CLEAR_META_RESV &&
|
if (bits & EXTENT_CLEAR_META_RESV &&
|
||||||
root != fs_info->tree_root)
|
root != fs_info->tree_root)
|
||||||
btrfs_delalloc_release_metadata(inode, len, false);
|
btrfs_delalloc_release_metadata(inode, len, true);
|
||||||
|
|
||||||
/* For sanity tests. */
|
/* For sanity tests. */
|
||||||
if (btrfs_is_testing(fs_info))
|
if (btrfs_is_testing(fs_info))
|
||||||
|
@ -4503,6 +4503,7 @@ int btrfs_delete_subvolume(struct btrfs_inode *dir, struct dentry *dentry)
|
||||||
struct btrfs_trans_handle *trans;
|
struct btrfs_trans_handle *trans;
|
||||||
struct btrfs_block_rsv block_rsv;
|
struct btrfs_block_rsv block_rsv;
|
||||||
u64 root_flags;
|
u64 root_flags;
|
||||||
|
u64 qgroup_reserved = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
down_write(&fs_info->subvol_sem);
|
down_write(&fs_info->subvol_sem);
|
||||||
|
@ -4547,12 +4548,20 @@ int btrfs_delete_subvolume(struct btrfs_inode *dir, struct dentry *dentry)
|
||||||
ret = btrfs_subvolume_reserve_metadata(root, &block_rsv, 5, true);
|
ret = btrfs_subvolume_reserve_metadata(root, &block_rsv, 5, true);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_undead;
|
goto out_undead;
|
||||||
|
qgroup_reserved = block_rsv.qgroup_rsv_reserved;
|
||||||
|
|
||||||
trans = btrfs_start_transaction(root, 0);
|
trans = btrfs_start_transaction(root, 0);
|
||||||
if (IS_ERR(trans)) {
|
if (IS_ERR(trans)) {
|
||||||
ret = PTR_ERR(trans);
|
ret = PTR_ERR(trans);
|
||||||
goto out_release;
|
goto out_release;
|
||||||
}
|
}
|
||||||
|
ret = btrfs_record_root_in_trans(trans, root);
|
||||||
|
if (ret) {
|
||||||
|
btrfs_abort_transaction(trans, ret);
|
||||||
|
goto out_end_trans;
|
||||||
|
}
|
||||||
|
btrfs_qgroup_convert_reserved_meta(root, qgroup_reserved);
|
||||||
|
qgroup_reserved = 0;
|
||||||
trans->block_rsv = &block_rsv;
|
trans->block_rsv = &block_rsv;
|
||||||
trans->bytes_reserved = block_rsv.size;
|
trans->bytes_reserved = block_rsv.size;
|
||||||
|
|
||||||
|
@ -4611,7 +4620,9 @@ out_end_trans:
|
||||||
ret = btrfs_end_transaction(trans);
|
ret = btrfs_end_transaction(trans);
|
||||||
inode->i_flags |= S_DEAD;
|
inode->i_flags |= S_DEAD;
|
||||||
out_release:
|
out_release:
|
||||||
btrfs_subvolume_release_metadata(root, &block_rsv);
|
btrfs_block_rsv_release(fs_info, &block_rsv, (u64)-1, NULL);
|
||||||
|
if (qgroup_reserved)
|
||||||
|
btrfs_qgroup_free_meta_prealloc(root, qgroup_reserved);
|
||||||
out_undead:
|
out_undead:
|
||||||
if (ret) {
|
if (ret) {
|
||||||
spin_lock(&dest->root_item_lock);
|
spin_lock(&dest->root_item_lock);
|
||||||
|
|
|
@ -613,6 +613,7 @@ static noinline int create_subvol(struct mnt_idmap *idmap,
|
||||||
int ret;
|
int ret;
|
||||||
dev_t anon_dev;
|
dev_t anon_dev;
|
||||||
u64 objectid;
|
u64 objectid;
|
||||||
|
u64 qgroup_reserved = 0;
|
||||||
|
|
||||||
root_item = kzalloc(sizeof(*root_item), GFP_KERNEL);
|
root_item = kzalloc(sizeof(*root_item), GFP_KERNEL);
|
||||||
if (!root_item)
|
if (!root_item)
|
||||||
|
@ -650,13 +651,18 @@ static noinline int create_subvol(struct mnt_idmap *idmap,
|
||||||
trans_num_items, false);
|
trans_num_items, false);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_new_inode_args;
|
goto out_new_inode_args;
|
||||||
|
qgroup_reserved = block_rsv.qgroup_rsv_reserved;
|
||||||
|
|
||||||
trans = btrfs_start_transaction(root, 0);
|
trans = btrfs_start_transaction(root, 0);
|
||||||
if (IS_ERR(trans)) {
|
if (IS_ERR(trans)) {
|
||||||
ret = PTR_ERR(trans);
|
ret = PTR_ERR(trans);
|
||||||
btrfs_subvolume_release_metadata(root, &block_rsv);
|
goto out_release_rsv;
|
||||||
goto out_new_inode_args;
|
|
||||||
}
|
}
|
||||||
|
ret = btrfs_record_root_in_trans(trans, BTRFS_I(dir)->root);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
btrfs_qgroup_convert_reserved_meta(root, qgroup_reserved);
|
||||||
|
qgroup_reserved = 0;
|
||||||
trans->block_rsv = &block_rsv;
|
trans->block_rsv = &block_rsv;
|
||||||
trans->bytes_reserved = block_rsv.size;
|
trans->bytes_reserved = block_rsv.size;
|
||||||
/* Tree log can't currently deal with an inode which is a new root. */
|
/* Tree log can't currently deal with an inode which is a new root. */
|
||||||
|
@ -767,9 +773,11 @@ static noinline int create_subvol(struct mnt_idmap *idmap,
|
||||||
out:
|
out:
|
||||||
trans->block_rsv = NULL;
|
trans->block_rsv = NULL;
|
||||||
trans->bytes_reserved = 0;
|
trans->bytes_reserved = 0;
|
||||||
btrfs_subvolume_release_metadata(root, &block_rsv);
|
|
||||||
|
|
||||||
btrfs_end_transaction(trans);
|
btrfs_end_transaction(trans);
|
||||||
|
out_release_rsv:
|
||||||
|
btrfs_block_rsv_release(fs_info, &block_rsv, (u64)-1, NULL);
|
||||||
|
if (qgroup_reserved)
|
||||||
|
btrfs_qgroup_free_meta_prealloc(root, qgroup_reserved);
|
||||||
out_new_inode_args:
|
out_new_inode_args:
|
||||||
btrfs_new_inode_args_destroy(&new_inode_args);
|
btrfs_new_inode_args_destroy(&new_inode_args);
|
||||||
out_inode:
|
out_inode:
|
||||||
|
@ -791,6 +799,8 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
|
||||||
struct btrfs_pending_snapshot *pending_snapshot;
|
struct btrfs_pending_snapshot *pending_snapshot;
|
||||||
unsigned int trans_num_items;
|
unsigned int trans_num_items;
|
||||||
struct btrfs_trans_handle *trans;
|
struct btrfs_trans_handle *trans;
|
||||||
|
struct btrfs_block_rsv *block_rsv;
|
||||||
|
u64 qgroup_reserved = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* We do not support snapshotting right now. */
|
/* We do not support snapshotting right now. */
|
||||||
|
@ -827,19 +837,19 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
|
||||||
goto free_pending;
|
goto free_pending;
|
||||||
}
|
}
|
||||||
|
|
||||||
btrfs_init_block_rsv(&pending_snapshot->block_rsv,
|
block_rsv = &pending_snapshot->block_rsv;
|
||||||
BTRFS_BLOCK_RSV_TEMP);
|
btrfs_init_block_rsv(block_rsv, BTRFS_BLOCK_RSV_TEMP);
|
||||||
/*
|
/*
|
||||||
* 1 to add dir item
|
* 1 to add dir item
|
||||||
* 1 to add dir index
|
* 1 to add dir index
|
||||||
* 1 to update parent inode item
|
* 1 to update parent inode item
|
||||||
*/
|
*/
|
||||||
trans_num_items = create_subvol_num_items(inherit) + 3;
|
trans_num_items = create_subvol_num_items(inherit) + 3;
|
||||||
ret = btrfs_subvolume_reserve_metadata(BTRFS_I(dir)->root,
|
ret = btrfs_subvolume_reserve_metadata(BTRFS_I(dir)->root, block_rsv,
|
||||||
&pending_snapshot->block_rsv,
|
|
||||||
trans_num_items, false);
|
trans_num_items, false);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto free_pending;
|
goto free_pending;
|
||||||
|
qgroup_reserved = block_rsv->qgroup_rsv_reserved;
|
||||||
|
|
||||||
pending_snapshot->dentry = dentry;
|
pending_snapshot->dentry = dentry;
|
||||||
pending_snapshot->root = root;
|
pending_snapshot->root = root;
|
||||||
|
@ -852,6 +862,13 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
|
||||||
ret = PTR_ERR(trans);
|
ret = PTR_ERR(trans);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
ret = btrfs_record_root_in_trans(trans, BTRFS_I(dir)->root);
|
||||||
|
if (ret) {
|
||||||
|
btrfs_end_transaction(trans);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
btrfs_qgroup_convert_reserved_meta(root, qgroup_reserved);
|
||||||
|
qgroup_reserved = 0;
|
||||||
|
|
||||||
trans->pending_snapshot = pending_snapshot;
|
trans->pending_snapshot = pending_snapshot;
|
||||||
|
|
||||||
|
@ -881,7 +898,9 @@ fail:
|
||||||
if (ret && pending_snapshot->snap)
|
if (ret && pending_snapshot->snap)
|
||||||
pending_snapshot->snap->anon_dev = 0;
|
pending_snapshot->snap->anon_dev = 0;
|
||||||
btrfs_put_root(pending_snapshot->snap);
|
btrfs_put_root(pending_snapshot->snap);
|
||||||
btrfs_subvolume_release_metadata(root, &pending_snapshot->block_rsv);
|
btrfs_block_rsv_release(fs_info, block_rsv, (u64)-1, NULL);
|
||||||
|
if (qgroup_reserved)
|
||||||
|
btrfs_qgroup_free_meta_prealloc(root, qgroup_reserved);
|
||||||
free_pending:
|
free_pending:
|
||||||
if (pending_snapshot->anon_dev)
|
if (pending_snapshot->anon_dev)
|
||||||
free_anon_bdev(pending_snapshot->anon_dev);
|
free_anon_bdev(pending_snapshot->anon_dev);
|
||||||
|
|
|
@ -4495,6 +4495,8 @@ void btrfs_qgroup_convert_reserved_meta(struct btrfs_root *root, int num_bytes)
|
||||||
BTRFS_QGROUP_RSV_META_PREALLOC);
|
BTRFS_QGROUP_RSV_META_PREALLOC);
|
||||||
trace_qgroup_meta_convert(root, num_bytes);
|
trace_qgroup_meta_convert(root, num_bytes);
|
||||||
qgroup_convert_meta(fs_info, root->root_key.objectid, num_bytes);
|
qgroup_convert_meta(fs_info, root->root_key.objectid, num_bytes);
|
||||||
|
if (!sb_rdonly(fs_info->sb))
|
||||||
|
add_root_meta_rsv(root, num_bytes, BTRFS_QGROUP_RSV_META_PERTRANS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -548,13 +548,3 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void btrfs_subvolume_release_metadata(struct btrfs_root *root,
|
|
||||||
struct btrfs_block_rsv *rsv)
|
|
||||||
{
|
|
||||||
struct btrfs_fs_info *fs_info = root->fs_info;
|
|
||||||
u64 qgroup_to_release;
|
|
||||||
|
|
||||||
btrfs_block_rsv_release(fs_info, rsv, (u64)-1, &qgroup_to_release);
|
|
||||||
btrfs_qgroup_convert_reserved_meta(root, qgroup_to_release);
|
|
||||||
}
|
|
||||||
|
|
|
@ -18,8 +18,6 @@ struct btrfs_trans_handle;
|
||||||
int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
|
int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
|
||||||
struct btrfs_block_rsv *rsv,
|
struct btrfs_block_rsv *rsv,
|
||||||
int nitems, bool use_global_rsv);
|
int nitems, bool use_global_rsv);
|
||||||
void btrfs_subvolume_release_metadata(struct btrfs_root *root,
|
|
||||||
struct btrfs_block_rsv *rsv);
|
|
||||||
int btrfs_add_root_ref(struct btrfs_trans_handle *trans, u64 root_id,
|
int btrfs_add_root_ref(struct btrfs_trans_handle *trans, u64 root_id,
|
||||||
u64 ref_id, u64 dirid, u64 sequence,
|
u64 ref_id, u64 dirid, u64 sequence,
|
||||||
const struct fscrypt_str *name);
|
const struct fscrypt_str *name);
|
||||||
|
|
|
@ -745,14 +745,6 @@ again:
|
||||||
h->reloc_reserved = reloc_reserved;
|
h->reloc_reserved = reloc_reserved;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Now that we have found a transaction to be a part of, convert the
|
|
||||||
* qgroup reservation from prealloc to pertrans. A different transaction
|
|
||||||
* can't race in and free our pertrans out from under us.
|
|
||||||
*/
|
|
||||||
if (qgroup_reserved)
|
|
||||||
btrfs_qgroup_convert_reserved_meta(root, qgroup_reserved);
|
|
||||||
|
|
||||||
got_it:
|
got_it:
|
||||||
if (!current->journal_info)
|
if (!current->journal_info)
|
||||||
current->journal_info = h;
|
current->journal_info = h;
|
||||||
|
@ -786,8 +778,15 @@ got_it:
|
||||||
* not just freed.
|
* not just freed.
|
||||||
*/
|
*/
|
||||||
btrfs_end_transaction(h);
|
btrfs_end_transaction(h);
|
||||||
return ERR_PTR(ret);
|
goto reserve_fail;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Now that we have found a transaction to be a part of, convert the
|
||||||
|
* qgroup reservation from prealloc to pertrans. A different transaction
|
||||||
|
* can't race in and free our pertrans out from under us.
|
||||||
|
*/
|
||||||
|
if (qgroup_reserved)
|
||||||
|
btrfs_qgroup_convert_reserved_meta(root, qgroup_reserved);
|
||||||
|
|
||||||
return h;
|
return h;
|
||||||
|
|
||||||
|
@ -1495,6 +1494,7 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans)
|
||||||
radix_tree_tag_clear(&fs_info->fs_roots_radix,
|
radix_tree_tag_clear(&fs_info->fs_roots_radix,
|
||||||
(unsigned long)root->root_key.objectid,
|
(unsigned long)root->root_key.objectid,
|
||||||
BTRFS_ROOT_TRANS_TAG);
|
BTRFS_ROOT_TRANS_TAG);
|
||||||
|
btrfs_qgroup_free_meta_all_pertrans(root);
|
||||||
spin_unlock(&fs_info->fs_roots_radix_lock);
|
spin_unlock(&fs_info->fs_roots_radix_lock);
|
||||||
|
|
||||||
btrfs_free_log(trans, root);
|
btrfs_free_log(trans, root);
|
||||||
|
@ -1519,7 +1519,6 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans)
|
||||||
if (ret2)
|
if (ret2)
|
||||||
return ret2;
|
return ret2;
|
||||||
spin_lock(&fs_info->fs_roots_radix_lock);
|
spin_lock(&fs_info->fs_roots_radix_lock);
|
||||||
btrfs_qgroup_free_meta_all_pertrans(root);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_unlock(&fs_info->fs_roots_radix_lock);
|
spin_unlock(&fs_info->fs_roots_radix_lock);
|
||||||
|
|
Loading…
Reference in New Issue