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)
|
||||
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);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -2533,7 +2533,7 @@ void btrfs_clear_delalloc_extent(struct btrfs_inode *inode,
|
|||
*/
|
||||
if (bits & EXTENT_CLEAR_META_RESV &&
|
||||
root != fs_info->tree_root)
|
||||
btrfs_delalloc_release_metadata(inode, len, false);
|
||||
btrfs_delalloc_release_metadata(inode, len, true);
|
||||
|
||||
/* For sanity tests. */
|
||||
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_block_rsv block_rsv;
|
||||
u64 root_flags;
|
||||
u64 qgroup_reserved = 0;
|
||||
int ret;
|
||||
|
||||
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);
|
||||
if (ret)
|
||||
goto out_undead;
|
||||
qgroup_reserved = block_rsv.qgroup_rsv_reserved;
|
||||
|
||||
trans = btrfs_start_transaction(root, 0);
|
||||
if (IS_ERR(trans)) {
|
||||
ret = PTR_ERR(trans);
|
||||
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->bytes_reserved = block_rsv.size;
|
||||
|
||||
|
@ -4611,7 +4620,9 @@ out_end_trans:
|
|||
ret = btrfs_end_transaction(trans);
|
||||
inode->i_flags |= S_DEAD;
|
||||
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:
|
||||
if (ret) {
|
||||
spin_lock(&dest->root_item_lock);
|
||||
|
|
|
@ -613,6 +613,7 @@ static noinline int create_subvol(struct mnt_idmap *idmap,
|
|||
int ret;
|
||||
dev_t anon_dev;
|
||||
u64 objectid;
|
||||
u64 qgroup_reserved = 0;
|
||||
|
||||
root_item = kzalloc(sizeof(*root_item), GFP_KERNEL);
|
||||
if (!root_item)
|
||||
|
@ -650,13 +651,18 @@ static noinline int create_subvol(struct mnt_idmap *idmap,
|
|||
trans_num_items, false);
|
||||
if (ret)
|
||||
goto out_new_inode_args;
|
||||
qgroup_reserved = block_rsv.qgroup_rsv_reserved;
|
||||
|
||||
trans = btrfs_start_transaction(root, 0);
|
||||
if (IS_ERR(trans)) {
|
||||
ret = PTR_ERR(trans);
|
||||
btrfs_subvolume_release_metadata(root, &block_rsv);
|
||||
goto out_new_inode_args;
|
||||
goto out_release_rsv;
|
||||
}
|
||||
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->bytes_reserved = block_rsv.size;
|
||||
/* 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:
|
||||
trans->block_rsv = NULL;
|
||||
trans->bytes_reserved = 0;
|
||||
btrfs_subvolume_release_metadata(root, &block_rsv);
|
||||
|
||||
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:
|
||||
btrfs_new_inode_args_destroy(&new_inode_args);
|
||||
out_inode:
|
||||
|
@ -791,6 +799,8 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
|
|||
struct btrfs_pending_snapshot *pending_snapshot;
|
||||
unsigned int trans_num_items;
|
||||
struct btrfs_trans_handle *trans;
|
||||
struct btrfs_block_rsv *block_rsv;
|
||||
u64 qgroup_reserved = 0;
|
||||
int ret;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
btrfs_init_block_rsv(&pending_snapshot->block_rsv,
|
||||
BTRFS_BLOCK_RSV_TEMP);
|
||||
block_rsv = &pending_snapshot->block_rsv;
|
||||
btrfs_init_block_rsv(block_rsv, BTRFS_BLOCK_RSV_TEMP);
|
||||
/*
|
||||
* 1 to add dir item
|
||||
* 1 to add dir index
|
||||
* 1 to update parent inode item
|
||||
*/
|
||||
trans_num_items = create_subvol_num_items(inherit) + 3;
|
||||
ret = btrfs_subvolume_reserve_metadata(BTRFS_I(dir)->root,
|
||||
&pending_snapshot->block_rsv,
|
||||
ret = btrfs_subvolume_reserve_metadata(BTRFS_I(dir)->root, block_rsv,
|
||||
trans_num_items, false);
|
||||
if (ret)
|
||||
goto free_pending;
|
||||
qgroup_reserved = block_rsv->qgroup_rsv_reserved;
|
||||
|
||||
pending_snapshot->dentry = dentry;
|
||||
pending_snapshot->root = root;
|
||||
|
@ -852,6 +862,13 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
|
|||
ret = PTR_ERR(trans);
|
||||
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;
|
||||
|
||||
|
@ -881,7 +898,9 @@ fail:
|
|||
if (ret && pending_snapshot->snap)
|
||||
pending_snapshot->snap->anon_dev = 0;
|
||||
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:
|
||||
if (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);
|
||||
trace_qgroup_meta_convert(root, 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;
|
||||
}
|
||||
|
||||
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,
|
||||
struct btrfs_block_rsv *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,
|
||||
u64 ref_id, u64 dirid, u64 sequence,
|
||||
const struct fscrypt_str *name);
|
||||
|
|
|
@ -745,14 +745,6 @@ again:
|
|||
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:
|
||||
if (!current->journal_info)
|
||||
current->journal_info = h;
|
||||
|
@ -786,8 +778,15 @@ got_it:
|
|||
* not just freed.
|
||||
*/
|
||||
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;
|
||||
|
||||
|
@ -1495,6 +1494,7 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans)
|
|||
radix_tree_tag_clear(&fs_info->fs_roots_radix,
|
||||
(unsigned long)root->root_key.objectid,
|
||||
BTRFS_ROOT_TRANS_TAG);
|
||||
btrfs_qgroup_free_meta_all_pertrans(root);
|
||||
spin_unlock(&fs_info->fs_roots_radix_lock);
|
||||
|
||||
btrfs_free_log(trans, root);
|
||||
|
@ -1519,7 +1519,6 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans)
|
|||
if (ret2)
|
||||
return ret2;
|
||||
spin_lock(&fs_info->fs_roots_radix_lock);
|
||||
btrfs_qgroup_free_meta_all_pertrans(root);
|
||||
}
|
||||
}
|
||||
spin_unlock(&fs_info->fs_roots_radix_lock);
|
||||
|
|
Loading…
Reference in New Issue