Skip to content

Commit 20cb38a

Browse files
committed
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
2 parents 4f0a8fe + 6e68de0 commit 20cb38a

File tree

7 files changed

+55
-33
lines changed

7 files changed

+55
-33
lines changed

fs/btrfs/delayed-inode.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,6 +1133,9 @@ __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans,
11331133
if (ret)
11341134
return ret;
11351135

1136+
ret = btrfs_record_root_in_trans(trans, node->root);
1137+
if (ret)
1138+
return ret;
11361139
ret = btrfs_update_delayed_inode(trans, node->root, path, node);
11371140
return ret;
11381141
}

fs/btrfs/inode.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2533,7 +2533,7 @@ void btrfs_clear_delalloc_extent(struct btrfs_inode *inode,
25332533
*/
25342534
if (bits & EXTENT_CLEAR_META_RESV &&
25352535
root != fs_info->tree_root)
2536-
btrfs_delalloc_release_metadata(inode, len, false);
2536+
btrfs_delalloc_release_metadata(inode, len, true);
25372537

25382538
/* For sanity tests. */
25392539
if (btrfs_is_testing(fs_info))
@@ -4503,6 +4503,7 @@ int btrfs_delete_subvolume(struct btrfs_inode *dir, struct dentry *dentry)
45034503
struct btrfs_trans_handle *trans;
45044504
struct btrfs_block_rsv block_rsv;
45054505
u64 root_flags;
4506+
u64 qgroup_reserved = 0;
45064507
int ret;
45074508

45084509
down_write(&fs_info->subvol_sem);
@@ -4547,12 +4548,20 @@ int btrfs_delete_subvolume(struct btrfs_inode *dir, struct dentry *dentry)
45474548
ret = btrfs_subvolume_reserve_metadata(root, &block_rsv, 5, true);
45484549
if (ret)
45494550
goto out_undead;
4551+
qgroup_reserved = block_rsv.qgroup_rsv_reserved;
45504552

45514553
trans = btrfs_start_transaction(root, 0);
45524554
if (IS_ERR(trans)) {
45534555
ret = PTR_ERR(trans);
45544556
goto out_release;
45554557
}
4558+
ret = btrfs_record_root_in_trans(trans, root);
4559+
if (ret) {
4560+
btrfs_abort_transaction(trans, ret);
4561+
goto out_end_trans;
4562+
}
4563+
btrfs_qgroup_convert_reserved_meta(root, qgroup_reserved);
4564+
qgroup_reserved = 0;
45564565
trans->block_rsv = &block_rsv;
45574566
trans->bytes_reserved = block_rsv.size;
45584567

@@ -4611,7 +4620,9 @@ int btrfs_delete_subvolume(struct btrfs_inode *dir, struct dentry *dentry)
46114620
ret = btrfs_end_transaction(trans);
46124621
inode->i_flags |= S_DEAD;
46134622
out_release:
4614-
btrfs_subvolume_release_metadata(root, &block_rsv);
4623+
btrfs_block_rsv_release(fs_info, &block_rsv, (u64)-1, NULL);
4624+
if (qgroup_reserved)
4625+
btrfs_qgroup_free_meta_prealloc(root, qgroup_reserved);
46154626
out_undead:
46164627
if (ret) {
46174628
spin_lock(&dest->root_item_lock);

fs/btrfs/ioctl.c

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,7 @@ static noinline int create_subvol(struct mnt_idmap *idmap,
613613
int ret;
614614
dev_t anon_dev;
615615
u64 objectid;
616+
u64 qgroup_reserved = 0;
616617

617618
root_item = kzalloc(sizeof(*root_item), GFP_KERNEL);
618619
if (!root_item)
@@ -650,13 +651,18 @@ static noinline int create_subvol(struct mnt_idmap *idmap,
650651
trans_num_items, false);
651652
if (ret)
652653
goto out_new_inode_args;
654+
qgroup_reserved = block_rsv.qgroup_rsv_reserved;
653655

654656
trans = btrfs_start_transaction(root, 0);
655657
if (IS_ERR(trans)) {
656658
ret = PTR_ERR(trans);
657-
btrfs_subvolume_release_metadata(root, &block_rsv);
658-
goto out_new_inode_args;
659+
goto out_release_rsv;
659660
}
661+
ret = btrfs_record_root_in_trans(trans, BTRFS_I(dir)->root);
662+
if (ret)
663+
goto out;
664+
btrfs_qgroup_convert_reserved_meta(root, qgroup_reserved);
665+
qgroup_reserved = 0;
660666
trans->block_rsv = &block_rsv;
661667
trans->bytes_reserved = block_rsv.size;
662668
/* 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,
767773
out:
768774
trans->block_rsv = NULL;
769775
trans->bytes_reserved = 0;
770-
btrfs_subvolume_release_metadata(root, &block_rsv);
771-
772776
btrfs_end_transaction(trans);
777+
out_release_rsv:
778+
btrfs_block_rsv_release(fs_info, &block_rsv, (u64)-1, NULL);
779+
if (qgroup_reserved)
780+
btrfs_qgroup_free_meta_prealloc(root, qgroup_reserved);
773781
out_new_inode_args:
774782
btrfs_new_inode_args_destroy(&new_inode_args);
775783
out_inode:
@@ -791,6 +799,8 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
791799
struct btrfs_pending_snapshot *pending_snapshot;
792800
unsigned int trans_num_items;
793801
struct btrfs_trans_handle *trans;
802+
struct btrfs_block_rsv *block_rsv;
803+
u64 qgroup_reserved = 0;
794804
int ret;
795805

796806
/* We do not support snapshotting right now. */
@@ -827,19 +837,19 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
827837
goto free_pending;
828838
}
829839

830-
btrfs_init_block_rsv(&pending_snapshot->block_rsv,
831-
BTRFS_BLOCK_RSV_TEMP);
840+
block_rsv = &pending_snapshot->block_rsv;
841+
btrfs_init_block_rsv(block_rsv, BTRFS_BLOCK_RSV_TEMP);
832842
/*
833843
* 1 to add dir item
834844
* 1 to add dir index
835845
* 1 to update parent inode item
836846
*/
837847
trans_num_items = create_subvol_num_items(inherit) + 3;
838-
ret = btrfs_subvolume_reserve_metadata(BTRFS_I(dir)->root,
839-
&pending_snapshot->block_rsv,
848+
ret = btrfs_subvolume_reserve_metadata(BTRFS_I(dir)->root, block_rsv,
840849
trans_num_items, false);
841850
if (ret)
842851
goto free_pending;
852+
qgroup_reserved = block_rsv->qgroup_rsv_reserved;
843853

844854
pending_snapshot->dentry = dentry;
845855
pending_snapshot->root = root;
@@ -852,6 +862,13 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
852862
ret = PTR_ERR(trans);
853863
goto fail;
854864
}
865+
ret = btrfs_record_root_in_trans(trans, BTRFS_I(dir)->root);
866+
if (ret) {
867+
btrfs_end_transaction(trans);
868+
goto fail;
869+
}
870+
btrfs_qgroup_convert_reserved_meta(root, qgroup_reserved);
871+
qgroup_reserved = 0;
855872

856873
trans->pending_snapshot = pending_snapshot;
857874

@@ -881,7 +898,9 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
881898
if (ret && pending_snapshot->snap)
882899
pending_snapshot->snap->anon_dev = 0;
883900
btrfs_put_root(pending_snapshot->snap);
884-
btrfs_subvolume_release_metadata(root, &pending_snapshot->block_rsv);
901+
btrfs_block_rsv_release(fs_info, block_rsv, (u64)-1, NULL);
902+
if (qgroup_reserved)
903+
btrfs_qgroup_free_meta_prealloc(root, qgroup_reserved);
885904
free_pending:
886905
if (pending_snapshot->anon_dev)
887906
free_anon_bdev(pending_snapshot->anon_dev);

fs/btrfs/qgroup.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4495,6 +4495,8 @@ void btrfs_qgroup_convert_reserved_meta(struct btrfs_root *root, int num_bytes)
44954495
BTRFS_QGROUP_RSV_META_PREALLOC);
44964496
trace_qgroup_meta_convert(root, num_bytes);
44974497
qgroup_convert_meta(fs_info, root->root_key.objectid, num_bytes);
4498+
if (!sb_rdonly(fs_info->sb))
4499+
add_root_meta_rsv(root, num_bytes, BTRFS_QGROUP_RSV_META_PERTRANS);
44984500
}
44994501

45004502
/*

fs/btrfs/root-tree.c

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -548,13 +548,3 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
548548
}
549549
return ret;
550550
}
551-
552-
void btrfs_subvolume_release_metadata(struct btrfs_root *root,
553-
struct btrfs_block_rsv *rsv)
554-
{
555-
struct btrfs_fs_info *fs_info = root->fs_info;
556-
u64 qgroup_to_release;
557-
558-
btrfs_block_rsv_release(fs_info, rsv, (u64)-1, &qgroup_to_release);
559-
btrfs_qgroup_convert_reserved_meta(root, qgroup_to_release);
560-
}

fs/btrfs/root-tree.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ struct btrfs_trans_handle;
1818
int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
1919
struct btrfs_block_rsv *rsv,
2020
int nitems, bool use_global_rsv);
21-
void btrfs_subvolume_release_metadata(struct btrfs_root *root,
22-
struct btrfs_block_rsv *rsv);
2321
int btrfs_add_root_ref(struct btrfs_trans_handle *trans, u64 root_id,
2422
u64 ref_id, u64 dirid, u64 sequence,
2523
const struct fscrypt_str *name);

fs/btrfs/transaction.c

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -745,14 +745,6 @@ start_transaction(struct btrfs_root *root, unsigned int num_items,
745745
h->reloc_reserved = reloc_reserved;
746746
}
747747

748-
/*
749-
* Now that we have found a transaction to be a part of, convert the
750-
* qgroup reservation from prealloc to pertrans. A different transaction
751-
* can't race in and free our pertrans out from under us.
752-
*/
753-
if (qgroup_reserved)
754-
btrfs_qgroup_convert_reserved_meta(root, qgroup_reserved);
755-
756748
got_it:
757749
if (!current->journal_info)
758750
current->journal_info = h;
@@ -786,8 +778,15 @@ start_transaction(struct btrfs_root *root, unsigned int num_items,
786778
* not just freed.
787779
*/
788780
btrfs_end_transaction(h);
789-
return ERR_PTR(ret);
781+
goto reserve_fail;
790782
}
783+
/*
784+
* Now that we have found a transaction to be a part of, convert the
785+
* qgroup reservation from prealloc to pertrans. A different transaction
786+
* can't race in and free our pertrans out from under us.
787+
*/
788+
if (qgroup_reserved)
789+
btrfs_qgroup_convert_reserved_meta(root, qgroup_reserved);
791790

792791
return h;
793792

@@ -1495,6 +1494,7 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans)
14951494
radix_tree_tag_clear(&fs_info->fs_roots_radix,
14961495
(unsigned long)root->root_key.objectid,
14971496
BTRFS_ROOT_TRANS_TAG);
1497+
btrfs_qgroup_free_meta_all_pertrans(root);
14981498
spin_unlock(&fs_info->fs_roots_radix_lock);
14991499

15001500
btrfs_free_log(trans, root);
@@ -1519,7 +1519,6 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans)
15191519
if (ret2)
15201520
return ret2;
15211521
spin_lock(&fs_info->fs_roots_radix_lock);
1522-
btrfs_qgroup_free_meta_all_pertrans(root);
15231522
}
15241523
}
15251524
spin_unlock(&fs_info->fs_roots_radix_lock);

0 commit comments

Comments
 (0)