static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
+                              struct btrfs_delayed_ref_head *href,
                               struct btrfs_delayed_ref_node *node, u64 parent,
                               u64 root_objectid, u64 owner_objectid,
                               u64 owner_offset,
 }
 
 static int run_delayed_data_ref(struct btrfs_trans_handle *trans,
+                               struct btrfs_delayed_ref_head *href,
                                struct btrfs_delayed_ref_node *node,
                                struct btrfs_delayed_extent_op *extent_op,
                                bool insert_reserved)
 
        if (node->action == BTRFS_ADD_DELAYED_REF && insert_reserved) {
                struct btrfs_key key;
+               struct btrfs_squota_delta delta = {
+                       .root = href->owning_root,
+                       .num_bytes = node->num_bytes,
+                       .rsv_bytes = href->reserved_bytes,
+                       .is_data = true,
+                       .is_inc = true,
+               };
 
                if (extent_op)
                        flags |= extent_op->flags_to_set;
                                                 flags, ref->objectid,
                                                 ref->offset, &key,
                                                 node->ref_mod);
+               if (!ret)
+                       ret = btrfs_record_squota_delta(trans->fs_info, &delta);
+               else
+                       btrfs_qgroup_free_refroot(trans->fs_info, delta.root,
+                                                 delta.rsv_bytes, BTRFS_QGROUP_RSV_DATA);
        } else if (node->action == BTRFS_ADD_DELAYED_REF) {
                ret = __btrfs_inc_extent_ref(trans, node, parent, ref->root,
                                             ref->objectid, ref->offset,
                                             extent_op);
        } else if (node->action == BTRFS_DROP_DELAYED_REF) {
-               ret = __btrfs_free_extent(trans, node, parent,
+               ret = __btrfs_free_extent(trans, href, node, parent,
                                          ref->root, ref->objectid,
                                          ref->offset, extent_op);
        } else {
 }
 
 static int run_delayed_tree_ref(struct btrfs_trans_handle *trans,
+                               struct btrfs_delayed_ref_head *href,
                                struct btrfs_delayed_ref_node *node,
                                struct btrfs_delayed_extent_op *extent_op,
                                bool insert_reserved)
 {
        int ret = 0;
+       struct btrfs_fs_info *fs_info = trans->fs_info;
        struct btrfs_delayed_tree_ref *ref;
        u64 parent = 0;
        u64 ref_root = 0;
                return -EUCLEAN;
        }
        if (node->action == BTRFS_ADD_DELAYED_REF && insert_reserved) {
+               struct btrfs_squota_delta delta = {
+                       .root = href->owning_root,
+                       .num_bytes = fs_info->nodesize,
+                       .rsv_bytes = 0,
+                       .is_data = false,
+                       .is_inc = true,
+               };
+
                BUG_ON(!extent_op || !extent_op->update_flags);
                ret = alloc_reserved_tree_block(trans, node, extent_op);
+               if (!ret)
+                       btrfs_record_squota_delta(fs_info, &delta);
        } else if (node->action == BTRFS_ADD_DELAYED_REF) {
                ret = __btrfs_inc_extent_ref(trans, node, parent, ref_root,
                                             ref->level, 0, extent_op);
        } else if (node->action == BTRFS_DROP_DELAYED_REF) {
-               ret = __btrfs_free_extent(trans, node, parent, ref_root,
+               ret = __btrfs_free_extent(trans, href, node, parent, ref_root,
                                          ref->level, 0, extent_op);
        } else {
                BUG();
 
 /* helper function to actually process a single delayed ref entry */
 static int run_one_delayed_ref(struct btrfs_trans_handle *trans,
+                              struct btrfs_delayed_ref_head *href,
                               struct btrfs_delayed_ref_node *node,
                               struct btrfs_delayed_extent_op *extent_op,
                               bool insert_reserved)
 
        if (node->type == BTRFS_TREE_BLOCK_REF_KEY ||
            node->type == BTRFS_SHARED_BLOCK_REF_KEY)
-               ret = run_delayed_tree_ref(trans, node, extent_op,
+               ret = run_delayed_tree_ref(trans, href, node, extent_op,
                                           insert_reserved);
        else if (node->type == BTRFS_EXTENT_DATA_REF_KEY ||
                 node->type == BTRFS_SHARED_DATA_REF_KEY)
-               ret = run_delayed_data_ref(trans, node, extent_op,
+               ret = run_delayed_data_ref(trans, href, node, extent_op,
                                           insert_reserved);
        else if (node->type == BTRFS_EXTENT_OWNER_REF_KEY)
                ret = 0;
 
                return btrfs_calc_delayed_ref_csum_bytes(fs_info, nr_csums);
        }
+       if (btrfs_qgroup_mode(fs_info) == BTRFS_QGROUP_MODE_SIMPLE &&
+           head->must_insert_reserved && head->is_data)
+               btrfs_qgroup_free_refroot(fs_info, head->owning_root,
+                                         head->reserved_bytes, BTRFS_QGROUP_RSV_DATA);
 
        return 0;
 }
                locked_ref->extent_op = NULL;
                spin_unlock(&locked_ref->lock);
 
-               ret = run_one_delayed_ref(trans, ref, extent_op,
+               ret = run_one_delayed_ref(trans, locked_ref, ref, extent_op,
                                          must_insert_reserved);
                btrfs_delayed_refs_rsv_release(fs_info, 1, 0);
                *bytes_released += btrfs_calc_delayed_ref_bytes(fs_info, 1);
+
                btrfs_free_delayed_extent_op(extent_op);
                if (ret) {
                        unselect_delayed_ref_head(delayed_refs, locked_ref);
 }
 
 static int do_free_extent_accounting(struct btrfs_trans_handle *trans,
-                                    u64 bytenr, u64 num_bytes, bool is_data)
+                                    u64 bytenr, struct btrfs_squota_delta *delta)
 {
        int ret;
+       u64 num_bytes = delta->num_bytes;
 
-       if (is_data) {
+       if (delta->is_data) {
                struct btrfs_root *csum_root;
 
                csum_root = btrfs_csum_root(trans->fs_info, bytenr);
                }
        }
 
+       ret = btrfs_record_squota_delta(trans->fs_info, delta);
+       if (ret) {
+               btrfs_abort_transaction(trans, ret);
+               return ret;
+       }
+
        ret = add_to_free_space_tree(trans, bytenr, num_bytes);
        if (ret) {
                btrfs_abort_transaction(trans, ret);
  * And that (13631488 EXTENT_DATA_REF <HASH>) gets removed.
  */
 static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
+                              struct btrfs_delayed_ref_head *href,
                               struct btrfs_delayed_ref_node *node, u64 parent,
                               u64 root_objectid, u64 owner_objectid,
                               u64 owner_offset,
        u64 bytenr = node->bytenr;
        u64 num_bytes = node->num_bytes;
        bool skinny_metadata = btrfs_fs_incompat(info, SKINNY_METADATA);
+       u64 delayed_ref_root = href->owning_root;
 
        extent_root = btrfs_extent_root(info, bytenr);
        ASSERT(extent_root);
                        }
                }
        } else {
+               struct btrfs_squota_delta delta = {
+                       .root = delayed_ref_root,
+                       .num_bytes = num_bytes,
+                       .rsv_bytes = 0,
+                       .is_data = is_data,
+                       .is_inc = false,
+               };
+
                /* In this branch refs == 1 */
                if (found_extent) {
                        if (is_data && refs_to_drop !=
                                num_to_del = 2;
                        }
                }
+               /*
+                * We can't infer the data owner from the delayed ref, so we need
+                * to try to get it from the owning ref item.
+                *
+                * If it is not present, then that extent was not written under
+                * simple quotas mode, so we don't need to account for its deletion.
+                */
+               if (is_data)
+                       delta.root = btrfs_get_extent_owner_root(trans->fs_info,
+                                                                leaf, extent_slot);
 
                ret = btrfs_del_items(trans, extent_root, path, path->slots[0],
                                      num_to_del);
                }
                btrfs_release_path(path);
 
-               ret = do_free_extent_accounting(trans, bytenr, num_bytes, is_data);
+               ret = do_free_extent_accounting(trans, bytenr, &delta);
        }
        btrfs_release_path(path);
 
        int ret;
        struct btrfs_block_group *block_group;
        struct btrfs_space_info *space_info;
+       struct btrfs_squota_delta delta = {
+               .root = root_objectid,
+               .num_bytes = ins->offset,
+               .rsv_bytes = 0,
+               .is_data = true,
+               .is_inc = true,
+       };
 
        /*
         * Mixed block groups will exclude before processing the log so we only
                                         offset, ins, 1);
        if (ret)
                btrfs_pin_extent(trans, ins->objectid, ins->offset, 1);
+       ret = btrfs_record_squota_delta(fs_info, &delta);
        btrfs_put_block_group(block_group);
        return ret;
 }