diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 2df4bc77f5b477e6d0f403b4962256707462d6b7..6c7927cd4f411fc4302c1ce99394a2d7e33100e3 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -2345,6 +2345,11 @@ static int run_one_delayed_ref(struct btrfs_trans_handle *trans, node->num_bytes); } } + + /* Also free its reserved qgroup space */ + btrfs_qgroup_free_delayed_ref(root->fs_info, + head->qgroup_ref_root, + head->qgroup_reserved); return ret; } diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 5ce55f6eefceb8103ab6d8c7194c1797f0668ce3..c21ed7b1469131d23bc786bd5b28b603217ee852 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -2119,6 +2119,16 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans, ret = btrfs_alloc_reserved_file_extent(trans, root, root->root_key.objectid, btrfs_ino(inode), file_pos, &ins); + if (ret < 0) + goto out; + /* + * Release the reserved range from inode dirty range map, and + * move it to delayed ref codes, as now accounting only happens at + * commit_transaction() time. + */ + btrfs_qgroup_release_data(inode, file_pos, ram_bytes); + ret = btrfs_add_delayed_qgroup_reserve(root->fs_info, trans, + root->objectid, disk_bytenr, ram_bytes); out: btrfs_free_path(path); diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index e05d1f6aa293f0e95768032c96ba225777036f10..75d8e584c3e52bc02bca18e19352fc9a2ede50f8 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -2116,14 +2116,13 @@ int btrfs_qgroup_reserve(struct btrfs_root *root, u64 num_bytes) return ret; } -void btrfs_qgroup_free(struct btrfs_root *root, u64 num_bytes) +void btrfs_qgroup_free_refroot(struct btrfs_fs_info *fs_info, + u64 ref_root, u64 num_bytes) { struct btrfs_root *quota_root; struct btrfs_qgroup *qgroup; - struct btrfs_fs_info *fs_info = root->fs_info; struct ulist_node *unode; struct ulist_iterator uiter; - u64 ref_root = root->root_key.objectid; int ret = 0; if (!is_fstree(ref_root)) diff --git a/fs/btrfs/qgroup.h b/fs/btrfs/qgroup.h index 564eb214774091da9ba03499eac3415059d15981..80924aeceb09cc7b39f29c845bc51bb85775537a 100644 --- a/fs/btrfs/qgroup.h +++ b/fs/btrfs/qgroup.h @@ -72,7 +72,23 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, u64 srcid, u64 objectid, struct btrfs_qgroup_inherit *inherit); int btrfs_qgroup_reserve(struct btrfs_root *root, u64 num_bytes); -void btrfs_qgroup_free(struct btrfs_root *root, u64 num_bytes); +void btrfs_qgroup_free_refroot(struct btrfs_fs_info *fs_info, + u64 ref_root, u64 num_bytes); +static inline void btrfs_qgroup_free(struct btrfs_root *root, u64 num_bytes) +{ + return btrfs_qgroup_free_refroot(root->fs_info, root->objectid, + num_bytes); +} + +/* + * TODO: Add proper trace point for it, as btrfs_qgroup_free() is + * called by everywhere, can't provide good trace for delayed ref case. + */ +static inline void btrfs_qgroup_free_delayed_ref(struct btrfs_fs_info *fs_info, + u64 ref_root, u64 num_bytes) +{ + btrfs_qgroup_free_refroot(fs_info, ref_root, num_bytes); +} void assert_qgroups_uptodate(struct btrfs_trans_handle *trans);