btrfs: qgroup: simple quota auto hierarchy for nested subvolumes
[linux-2.6-microblaze.git] / fs / btrfs / extent-tree.c
index fc313fc..865c74d 100644 (file)
 #include "file-item.h"
 #include "orphan.h"
 #include "tree-checker.h"
+#include "raid-stripe-tree.h"
 
 #undef SCRAMBLE_DELAYED_REFS
 
 
 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, int refs_to_drop,
+                              u64 owner_offset,
                               struct btrfs_delayed_extent_op *extra_op);
 static void __run_delayed_extent_op(struct btrfs_delayed_extent_op *extent_op,
                                    struct extent_buffer *leaf,
@@ -344,9 +346,15 @@ int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb,
                                     struct btrfs_extent_inline_ref *iref,
                                     enum btrfs_inline_ref_type is_data)
 {
+       struct btrfs_fs_info *fs_info = eb->fs_info;
        int type = btrfs_extent_inline_ref_type(eb, iref);
        u64 offset = btrfs_extent_inline_ref_offset(eb, iref);
 
+       if (type == BTRFS_EXTENT_OWNER_REF_KEY) {
+               ASSERT(btrfs_fs_incompat(fs_info, SIMPLE_QUOTA));
+               return type;
+       }
+
        if (type == BTRFS_TREE_BLOCK_REF_KEY ||
            type == BTRFS_SHARED_BLOCK_REF_KEY ||
            type == BTRFS_SHARED_DATA_REF_KEY ||
@@ -355,26 +363,25 @@ int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb,
                        if (type == BTRFS_TREE_BLOCK_REF_KEY)
                                return type;
                        if (type == BTRFS_SHARED_BLOCK_REF_KEY) {
-                               ASSERT(eb->fs_info);
+                               ASSERT(fs_info);
                                /*
                                 * Every shared one has parent tree block,
                                 * which must be aligned to sector size.
                                 */
-                               if (offset &&
-                                   IS_ALIGNED(offset, eb->fs_info->sectorsize))
+                               if (offset && IS_ALIGNED(offset, fs_info->sectorsize))
                                        return type;
                        }
                } else if (is_data == BTRFS_REF_TYPE_DATA) {
                        if (type == BTRFS_EXTENT_DATA_REF_KEY)
                                return type;
                        if (type == BTRFS_SHARED_DATA_REF_KEY) {
-                               ASSERT(eb->fs_info);
+                               ASSERT(fs_info);
                                /*
                                 * Every shared one has parent tree block,
                                 * which must be aligned to sector size.
                                 */
                                if (offset &&
-                                   IS_ALIGNED(offset, eb->fs_info->sectorsize))
+                                   IS_ALIGNED(offset, fs_info->sectorsize))
                                        return type;
                        }
                } else {
@@ -385,7 +392,7 @@ int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb,
 
        WARN_ON(1);
        btrfs_print_leaf(eb);
-       btrfs_err(eb->fs_info,
+       btrfs_err(fs_info,
                  "eb %llu iref 0x%lx invalid extent inline ref type %d",
                  eb->start, (unsigned long)iref, type);
 
@@ -399,11 +406,11 @@ u64 hash_extent_data_ref(u64 root_objectid, u64 owner, u64 offset)
        __le64 lenum;
 
        lenum = cpu_to_le64(root_objectid);
-       high_crc = btrfs_crc32c(high_crc, &lenum, sizeof(lenum));
+       high_crc = crc32c(high_crc, &lenum, sizeof(lenum));
        lenum = cpu_to_le64(owner);
-       low_crc = btrfs_crc32c(low_crc, &lenum, sizeof(lenum));
+       low_crc = crc32c(low_crc, &lenum, sizeof(lenum));
        lenum = cpu_to_le64(offset);
-       low_crc = btrfs_crc32c(low_crc, &lenum, sizeof(lenum));
+       low_crc = crc32c(low_crc, &lenum, sizeof(lenum));
 
        return ((u64)high_crc << 31) ^ (u64)low_crc;
 }
@@ -575,7 +582,7 @@ static noinline int insert_extent_data_ref(struct btrfs_trans_handle *trans,
                        btrfs_set_extent_data_ref_count(leaf, ref, num_refs);
                }
        }
-       btrfs_mark_buffer_dirty(leaf);
+       btrfs_mark_buffer_dirty(trans, leaf);
        ret = 0;
 fail:
        btrfs_release_path(path);
@@ -623,7 +630,7 @@ static noinline int remove_extent_data_ref(struct btrfs_trans_handle *trans,
                        btrfs_set_extent_data_ref_count(leaf, ref1, num_refs);
                else if (key.type == BTRFS_SHARED_DATA_REF_KEY)
                        btrfs_set_shared_data_ref_count(leaf, ref2, num_refs);
-               btrfs_mark_buffer_dirty(leaf);
+               btrfs_mark_buffer_dirty(trans, leaf);
        }
        return ret;
 }
@@ -789,7 +796,6 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans,
        int type;
        int want;
        int ret;
-       int err = 0;
        bool skinny_metadata = btrfs_fs_incompat(fs_info, SKINNY_METADATA);
        int needed;
 
@@ -816,10 +822,8 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans,
 
 again:
        ret = btrfs_search_slot(trans, root, &key, path, extra_size, 1);
-       if (ret < 0) {
-               err = ret;
+       if (ret < 0)
                goto out;
-       }
 
        /*
         * We may be a newly converted file system which still has the old fat
@@ -846,7 +850,7 @@ again:
        }
 
        if (ret && !insert) {
-               err = -ENOENT;
+               ret = -ENOENT;
                goto out;
        } else if (WARN_ON(ret)) {
                btrfs_print_leaf(path->nodes[0]);
@@ -854,18 +858,18 @@ again:
 "extent item not found for insert, bytenr %llu num_bytes %llu parent %llu root_objectid %llu owner %llu offset %llu",
                          bytenr, num_bytes, parent, root_objectid, owner,
                          offset);
-               err = -EIO;
+               ret = -EUCLEAN;
                goto out;
        }
 
        leaf = path->nodes[0];
        item_size = btrfs_item_size(leaf, path->slots[0]);
        if (unlikely(item_size < sizeof(*ei))) {
-               err = -EUCLEAN;
+               ret = -EUCLEAN;
                btrfs_err(fs_info,
                          "unexpected extent item size, has %llu expect >= %zu",
                          item_size, sizeof(*ei));
-               btrfs_abort_transaction(trans, err);
+               btrfs_abort_transaction(trans, ret);
                goto out;
        }
 
@@ -885,22 +889,17 @@ again:
        else
                needed = BTRFS_REF_TYPE_BLOCK;
 
-       err = -ENOENT;
-       while (1) {
-               if (ptr >= end) {
-                       if (ptr > end) {
-                               err = -EUCLEAN;
-                               btrfs_print_leaf(path->nodes[0]);
-                               btrfs_crit(fs_info,
-"overrun extent record at slot %d while looking for inline extent for root %llu owner %llu offset %llu parent %llu",
-                                       path->slots[0], root_objectid, owner, offset, parent);
-                       }
-                       break;
-               }
+       ret = -ENOENT;
+       while (ptr < end) {
                iref = (struct btrfs_extent_inline_ref *)ptr;
                type = btrfs_get_extent_inline_ref_type(leaf, iref, needed);
+               if (type == BTRFS_EXTENT_OWNER_REF_KEY) {
+                       ASSERT(btrfs_fs_incompat(fs_info, SIMPLE_QUOTA));
+                       ptr += btrfs_extent_inline_ref_size(type);
+                       continue;
+               }
                if (type == BTRFS_REF_TYPE_INVALID) {
-                       err = -EUCLEAN;
+                       ret = -EUCLEAN;
                        goto out;
                }
 
@@ -916,7 +915,7 @@ again:
                        dref = (struct btrfs_extent_data_ref *)(&iref->offset);
                        if (match_extent_data_ref(leaf, dref, root_objectid,
                                                  owner, offset)) {
-                               err = 0;
+                               ret = 0;
                                break;
                        }
                        if (hash_extent_data_ref_item(leaf, dref) <
@@ -927,14 +926,14 @@ again:
                        ref_offset = btrfs_extent_inline_ref_offset(leaf, iref);
                        if (parent > 0) {
                                if (parent == ref_offset) {
-                                       err = 0;
+                                       ret = 0;
                                        break;
                                }
                                if (ref_offset < parent)
                                        break;
                        } else {
                                if (root_objectid == ref_offset) {
-                                       err = 0;
+                                       ret = 0;
                                        break;
                                }
                                if (ref_offset < root_objectid)
@@ -943,10 +942,20 @@ again:
                }
                ptr += btrfs_extent_inline_ref_size(type);
        }
-       if (err == -ENOENT && insert) {
+
+       if (unlikely(ptr > end)) {
+               ret = -EUCLEAN;
+               btrfs_print_leaf(path->nodes[0]);
+               btrfs_crit(fs_info,
+"overrun extent record at slot %d while looking for inline extent for root %llu owner %llu offset %llu parent %llu",
+                          path->slots[0], root_objectid, owner, offset, parent);
+               goto out;
+       }
+
+       if (ret == -ENOENT && insert) {
                if (item_size + extra_size >=
                    BTRFS_MAX_EXTENT_ITEM_SIZE(root)) {
-                       err = -EAGAIN;
+                       ret = -EAGAIN;
                        goto out;
                }
                /*
@@ -958,7 +967,7 @@ again:
                if (find_next_key(path, 0, &key) == 0 &&
                    key.objectid == bytenr &&
                    key.type < BTRFS_BLOCK_GROUP_ITEM_KEY) {
-                       err = -EAGAIN;
+                       ret = -EAGAIN;
                        goto out;
                }
        }
@@ -969,14 +978,14 @@ out:
                path->search_for_extension = 0;
                btrfs_unlock_up_safe(path, 1);
        }
-       return err;
+       return ret;
 }
 
 /*
  * helper to add new inline back ref
  */
 static noinline_for_stack
-void setup_inline_extent_backref(struct btrfs_fs_info *fs_info,
+void setup_inline_extent_backref(struct btrfs_trans_handle *trans,
                                 struct btrfs_path *path,
                                 struct btrfs_extent_inline_ref *iref,
                                 u64 parent, u64 root_objectid,
@@ -999,7 +1008,7 @@ void setup_inline_extent_backref(struct btrfs_fs_info *fs_info,
        type = extent_ref_type(parent, owner);
        size = btrfs_extent_inline_ref_size(type);
 
-       btrfs_extend_item(path, size);
+       btrfs_extend_item(trans, path, size);
 
        ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item);
        refs = btrfs_extent_refs(leaf, ei);
@@ -1033,7 +1042,7 @@ void setup_inline_extent_backref(struct btrfs_fs_info *fs_info,
        } else {
                btrfs_set_extent_inline_ref_offset(leaf, iref, root_objectid);
        }
-       btrfs_mark_buffer_dirty(leaf);
+       btrfs_mark_buffer_dirty(trans, leaf);
 }
 
 static int lookup_extent_backref(struct btrfs_trans_handle *trans,
@@ -1066,7 +1075,9 @@ static int lookup_extent_backref(struct btrfs_trans_handle *trans,
 /*
  * helper to update/remove inline back ref
  */
-static noinline_for_stack int update_inline_extent_backref(struct btrfs_path *path,
+static noinline_for_stack int update_inline_extent_backref(
+                                 struct btrfs_trans_handle *trans,
+                                 struct btrfs_path *path,
                                  struct btrfs_extent_inline_ref *iref,
                                  int refs_to_mod,
                                  struct btrfs_delayed_extent_op *extent_op)
@@ -1174,9 +1185,9 @@ static noinline_for_stack int update_inline_extent_backref(struct btrfs_path *pa
                        memmove_extent_buffer(leaf, ptr, ptr + size,
                                              end - ptr - size);
                item_size -= size;
-               btrfs_truncate_item(path, item_size, 1);
+               btrfs_truncate_item(trans, path, item_size, 1);
        }
-       btrfs_mark_buffer_dirty(leaf);
+       btrfs_mark_buffer_dirty(trans, leaf);
        return 0;
 }
 
@@ -1206,9 +1217,10 @@ int insert_inline_extent_backref(struct btrfs_trans_handle *trans,
                                   bytenr, num_bytes, root_objectid, path->slots[0]);
                        return -EUCLEAN;
                }
-               ret = update_inline_extent_backref(path, iref, refs_to_add, extent_op);
+               ret = update_inline_extent_backref(trans, path, iref,
+                                                  refs_to_add, extent_op);
        } else if (ret == -ENOENT) {
-               setup_inline_extent_backref(trans->fs_info, path, iref, parent,
+               setup_inline_extent_backref(trans, path, iref, parent,
                                            root_objectid, owner, offset,
                                            refs_to_add, extent_op);
                ret = 0;
@@ -1226,7 +1238,8 @@ static int remove_extent_backref(struct btrfs_trans_handle *trans,
 
        BUG_ON(!is_data && refs_to_drop != 1);
        if (iref)
-               ret = update_inline_extent_backref(path, iref, -refs_to_drop, NULL);
+               ret = update_inline_extent_backref(trans, path, iref,
+                                                  -refs_to_drop, NULL);
        else if (is_data)
                ret = remove_extent_data_ref(trans, root, path, refs_to_drop);
        else
@@ -1422,7 +1435,7 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
        ASSERT(generic_ref->type != BTRFS_REF_NOT_SET &&
               generic_ref->action);
        BUG_ON(generic_ref->type == BTRFS_REF_METADATA &&
-              generic_ref->tree_ref.owning_root == BTRFS_TREE_LOG_OBJECTID);
+              generic_ref->tree_ref.ref_root == BTRFS_TREE_LOG_OBJECTID);
 
        if (generic_ref->type == BTRFS_REF_METADATA)
                ret = btrfs_add_delayed_tree_ref(trans, generic_ref, NULL);
@@ -1435,7 +1448,7 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
 }
 
 /*
- * __btrfs_inc_extent_ref - insert backreference for a given extent
+ * Insert backreference for a given extent.
  *
  * The counterpart is in __btrfs_free_extent(), with examples and more details
  * how it works.
@@ -1465,8 +1478,6 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
  *                 always passed as 0. For data extents it is the fileoffset
  *                 this extent belongs to.
  *
- * @refs_to_add     Number of references to add
- *
  * @extent_op       Pointer to a structure, holding information necessary when
  *                  updating a tree block's flags
  *
@@ -1474,7 +1485,7 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
 static int __btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
                                  struct btrfs_delayed_ref_node *node,
                                  u64 parent, u64 root_objectid,
-                                 u64 owner, u64 offset, int refs_to_add,
+                                 u64 owner, u64 offset,
                                  struct btrfs_delayed_extent_op *extent_op)
 {
        struct btrfs_path *path;
@@ -1484,6 +1495,7 @@ static int __btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
        u64 bytenr = node->bytenr;
        u64 num_bytes = node->num_bytes;
        u64 refs;
+       int refs_to_add = node->ref_mod;
        int ret;
 
        path = btrfs_alloc_path();
@@ -1510,7 +1522,7 @@ static int __btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
        if (extent_op)
                __run_delayed_extent_op(extent_op, leaf, item);
 
-       btrfs_mark_buffer_dirty(leaf);
+       btrfs_mark_buffer_dirty(trans, leaf);
        btrfs_release_path(path);
 
        /* now insert the actual backref */
@@ -1530,44 +1542,56 @@ out:
 }
 
 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)
 {
        int ret = 0;
        struct btrfs_delayed_data_ref *ref;
-       struct btrfs_key ins;
        u64 parent = 0;
-       u64 ref_root = 0;
        u64 flags = 0;
 
-       ins.objectid = node->bytenr;
-       ins.offset = node->num_bytes;
-       ins.type = BTRFS_EXTENT_ITEM_KEY;
-
        ref = btrfs_delayed_node_to_data_ref(node);
        trace_run_delayed_data_ref(trans->fs_info, node, ref, node->action);
 
        if (node->type == BTRFS_SHARED_DATA_REF_KEY)
                parent = ref->parent;
-       ref_root = ref->root;
 
        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;
-               ret = alloc_reserved_file_extent(trans, parent, ref_root,
+
+               key.objectid = node->bytenr;
+               key.type = BTRFS_EXTENT_ITEM_KEY;
+               key.offset = node->num_bytes;
+
+               ret = alloc_reserved_file_extent(trans, parent, ref->root,
                                                 flags, ref->objectid,
-                                                ref->offset, &ins,
+                                                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,
+               ret = __btrfs_inc_extent_ref(trans, node, parent, ref->root,
                                             ref->objectid, ref->offset,
-                                            node->ref_mod, extent_op);
+                                            extent_op);
        } else if (node->action == BTRFS_DROP_DELAYED_REF) {
-               ret = __btrfs_free_extent(trans, node, parent,
-                                         ref_root, ref->objectid,
-                                         ref->offset, node->ref_mod,
-                                         extent_op);
+               ret = __btrfs_free_extent(trans, href, node, parent,
+                                         ref->root, ref->objectid,
+                                         ref->offset, extent_op);
        } else {
                BUG();
        }
@@ -1604,7 +1628,6 @@ static int run_delayed_extent_op(struct btrfs_trans_handle *trans,
        struct extent_buffer *leaf;
        u32 item_size;
        int ret;
-       int err = 0;
        int metadata = 1;
 
        if (TRANS_ABORTED(trans))
@@ -1631,10 +1654,8 @@ static int run_delayed_extent_op(struct btrfs_trans_handle *trans,
 again:
        ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
        if (ret < 0) {
-               err = ret;
                goto out;
-       }
-       if (ret > 0) {
+       } else if (ret > 0) {
                if (metadata) {
                        if (path->slots[0] > 0) {
                                path->slots[0]--;
@@ -1655,7 +1676,7 @@ again:
                                goto again;
                        }
                } else {
-                       err = -EUCLEAN;
+                       ret = -EUCLEAN;
                        btrfs_err(fs_info,
                  "missing extent item for extent %llu num_bytes %llu level %d",
                                  head->bytenr, head->num_bytes, extent_op->level);
@@ -1667,29 +1688,31 @@ again:
        item_size = btrfs_item_size(leaf, path->slots[0]);
 
        if (unlikely(item_size < sizeof(*ei))) {
-               err = -EUCLEAN;
+               ret = -EUCLEAN;
                btrfs_err(fs_info,
                          "unexpected extent item size, has %u expect >= %zu",
                          item_size, sizeof(*ei));
-               btrfs_abort_transaction(trans, err);
+               btrfs_abort_transaction(trans, ret);
                goto out;
        }
 
        ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item);
        __run_delayed_extent_op(extent_op, leaf, ei);
 
-       btrfs_mark_buffer_dirty(leaf);
+       btrfs_mark_buffer_dirty(trans, leaf);
 out:
        btrfs_free_path(path);
-       return err;
+       return ret;
 }
 
 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;
@@ -1709,14 +1732,24 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans,
                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, 1, extent_op);
+                                            ref->level, 0, extent_op);
        } else if (node->action == BTRFS_DROP_DELAYED_REF) {
-               ret = __btrfs_free_extent(trans, node, parent, ref_root,
-                                         ref->level, 0, 1, extent_op);
+               ret = __btrfs_free_extent(trans, href, node, parent, ref_root,
+                                         ref->level, 0, extent_op);
        } else {
                BUG();
        }
@@ -1725,6 +1758,7 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans,
 
 /* 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)
@@ -1739,12 +1773,14 @@ static int run_one_delayed_ref(struct btrfs_trans_handle *trans,
 
        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;
        else
                BUG();
        if (ret && insert_reserved)
@@ -1823,28 +1859,37 @@ static int run_and_cleanup_extent_op(struct btrfs_trans_handle *trans,
        return ret ? ret : 1;
 }
 
-void btrfs_cleanup_ref_head_accounting(struct btrfs_fs_info *fs_info,
+u64 btrfs_cleanup_ref_head_accounting(struct btrfs_fs_info *fs_info,
                                  struct btrfs_delayed_ref_root *delayed_refs,
                                  struct btrfs_delayed_ref_head *head)
 {
-       int nr_items = 1;       /* Dropping this ref head update. */
-
        /*
         * We had csum deletions accounted for in our delayed refs rsv, we need
         * to drop the csum leaves for this update from our delayed_refs_rsv.
         */
        if (head->total_ref_mod < 0 && head->is_data) {
+               int nr_csums;
+
                spin_lock(&delayed_refs->lock);
                delayed_refs->pending_csums -= head->num_bytes;
                spin_unlock(&delayed_refs->lock);
-               nr_items += btrfs_csum_bytes_to_leaves(fs_info, head->num_bytes);
+               nr_csums = btrfs_csum_bytes_to_leaves(fs_info, head->num_bytes);
+
+               btrfs_delayed_refs_rsv_release(fs_info, 0, nr_csums);
+
+               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);
 
-       btrfs_delayed_refs_rsv_release(fs_info, nr_items);
+       return 0;
 }
 
 static int cleanup_ref_head(struct btrfs_trans_handle *trans,
-                           struct btrfs_delayed_ref_head *head)
+                           struct btrfs_delayed_ref_head *head,
+                           u64 *bytes_released)
 {
 
        struct btrfs_fs_info *fs_info = trans->fs_info;
@@ -1889,7 +1934,7 @@ static int cleanup_ref_head(struct btrfs_trans_handle *trans,
                }
        }
 
-       btrfs_cleanup_ref_head_accounting(fs_info, delayed_refs, head);
+       *bytes_released += btrfs_cleanup_ref_head_accounting(fs_info, delayed_refs, head);
 
        trace_run_delayed_ref_head(fs_info, head, 0);
        btrfs_delayed_ref_unlock(head);
@@ -1931,7 +1976,8 @@ static struct btrfs_delayed_ref_head *btrfs_obtain_ref_head(
 }
 
 static int btrfs_run_delayed_refs_for_head(struct btrfs_trans_handle *trans,
-                                          struct btrfs_delayed_ref_head *locked_ref)
+                                          struct btrfs_delayed_ref_head *locked_ref,
+                                          u64 *bytes_released)
 {
        struct btrfs_fs_info *fs_info = trans->fs_info;
        struct btrfs_delayed_ref_root *delayed_refs;
@@ -1985,8 +2031,10 @@ static int btrfs_run_delayed_refs_for_head(struct btrfs_trans_handle *trans,
                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) {
@@ -2010,15 +2058,22 @@ static int btrfs_run_delayed_refs_for_head(struct btrfs_trans_handle *trans,
  * Returns -ENOMEM or -EIO on failure and will abort the transaction.
  */
 static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
-                                            unsigned long nr)
+                                            u64 min_bytes)
 {
        struct btrfs_fs_info *fs_info = trans->fs_info;
        struct btrfs_delayed_ref_root *delayed_refs;
        struct btrfs_delayed_ref_head *locked_ref = NULL;
        int ret;
        unsigned long count = 0;
+       unsigned long max_count = 0;
+       u64 bytes_processed = 0;
 
        delayed_refs = &trans->transaction->delayed_refs;
+       if (min_bytes == 0) {
+               max_count = delayed_refs->num_heads_ready;
+               min_bytes = U64_MAX;
+       }
+
        do {
                if (!locked_ref) {
                        locked_ref = btrfs_obtain_ref_head(trans);
@@ -2046,7 +2101,7 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
                spin_lock(&locked_ref->lock);
                btrfs_merge_delayed_refs(fs_info, delayed_refs, locked_ref);
 
-               ret = btrfs_run_delayed_refs_for_head(trans, locked_ref);
+               ret = btrfs_run_delayed_refs_for_head(trans, locked_ref, &bytes_processed);
                if (ret < 0 && ret != -EAGAIN) {
                        /*
                         * Error, btrfs_run_delayed_refs_for_head already
@@ -2058,7 +2113,7 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
                         * Success, perform the usual cleanup of a processed
                         * head
                         */
-                       ret = cleanup_ref_head(trans, locked_ref);
+                       ret = cleanup_ref_head(trans, locked_ref, &bytes_processed);
                        if (ret > 0 ) {
                                /* We dropped our lock, we need to loop. */
                                ret = 0;
@@ -2075,7 +2130,9 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
 
                locked_ref = NULL;
                cond_resched();
-       } while ((nr != -1 && count < nr) || locked_ref);
+       } while ((min_bytes != U64_MAX && bytes_processed < min_bytes) ||
+                (max_count > 0 && count < max_count) ||
+                locked_ref);
 
        return 0;
 }
@@ -2124,24 +2181,25 @@ static u64 find_middle(struct rb_root *root)
 #endif
 
 /*
- * this starts processing the delayed reference count updates and
- * extent insertions we have queued up so far.  count can be
- * 0, which means to process everything in the tree at the start
- * of the run (but not newly added entries), or it can be some target
- * number you'd like to process.
+ * Start processing the delayed reference count updates and extent insertions
+ * we have queued up so far.
+ *
+ * @trans:     Transaction handle.
+ * @min_bytes: How many bytes of delayed references to process. After this
+ *             many bytes we stop processing delayed references if there are
+ *             any more. If 0 it means to run all existing delayed references,
+ *             but not new ones added after running all existing ones.
+ *             Use (u64)-1 (U64_MAX) to run all existing delayed references
+ *             plus any new ones that are added.
  *
  * Returns 0 on success or if called with an aborted transaction
  * Returns <0 on error and aborts the transaction
  */
-int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
-                          unsigned long count)
+int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, u64 min_bytes)
 {
        struct btrfs_fs_info *fs_info = trans->fs_info;
-       struct rb_node *node;
        struct btrfs_delayed_ref_root *delayed_refs;
-       struct btrfs_delayed_ref_head *head;
        int ret;
-       int run_all = count == (unsigned long)-1;
 
        /* We'll clean this up in btrfs_cleanup_transaction */
        if (TRANS_ABORTED(trans))
@@ -2151,42 +2209,30 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
                return 0;
 
        delayed_refs = &trans->transaction->delayed_refs;
-       if (count == 0)
-               count = delayed_refs->num_heads_ready;
-
 again:
 #ifdef SCRAMBLE_DELAYED_REFS
        delayed_refs->run_delayed_start = find_middle(&delayed_refs->root);
 #endif
-       ret = __btrfs_run_delayed_refs(trans, count);
+       ret = __btrfs_run_delayed_refs(trans, min_bytes);
        if (ret < 0) {
                btrfs_abort_transaction(trans, ret);
                return ret;
        }
 
-       if (run_all) {
+       if (min_bytes == U64_MAX) {
                btrfs_create_pending_block_groups(trans);
 
                spin_lock(&delayed_refs->lock);
-               node = rb_first_cached(&delayed_refs->href_root);
-               if (!node) {
+               if (RB_EMPTY_ROOT(&delayed_refs->href_root.rb_root)) {
                        spin_unlock(&delayed_refs->lock);
-                       goto out;
+                       return 0;
                }
-               head = rb_entry(node, struct btrfs_delayed_ref_head,
-                               href_node);
-               refcount_inc(&head->refs);
                spin_unlock(&delayed_refs->lock);
 
-               /* Mutex was contended, block until it's released and retry. */
-               mutex_lock(&head->mutex);
-               mutex_unlock(&head->mutex);
-
-               btrfs_put_delayed_ref_head(head);
                cond_resched();
                goto again;
        }
-out:
+
        return 0;
 }
 
@@ -2311,6 +2357,7 @@ static noinline int check_committed_ref(struct btrfs_root *root,
        struct btrfs_extent_item *ei;
        struct btrfs_key key;
        u32 item_size;
+       u32 expected_size;
        int type;
        int ret;
 
@@ -2337,10 +2384,22 @@ static noinline int check_committed_ref(struct btrfs_root *root,
        ret = 1;
        item_size = btrfs_item_size(leaf, path->slots[0]);
        ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item);
+       expected_size = sizeof(*ei) + btrfs_extent_inline_ref_size(BTRFS_EXTENT_DATA_REF_KEY);
+
+       /* No inline refs; we need to bail before checking for owner ref. */
+       if (item_size == sizeof(*ei))
+               goto out;
+
+       /* Check for an owner ref; skip over it to the real inline refs. */
+       iref = (struct btrfs_extent_inline_ref *)(ei + 1);
+       type = btrfs_get_extent_inline_ref_type(leaf, iref, BTRFS_REF_TYPE_DATA);
+       if (btrfs_fs_incompat(fs_info, SIMPLE_QUOTA) && type == BTRFS_EXTENT_OWNER_REF_KEY) {
+               expected_size += btrfs_extent_inline_ref_size(BTRFS_EXTENT_OWNER_REF_KEY);
+               iref = (struct btrfs_extent_inline_ref *)(iref + 1);
+       }
 
        /* If extent item has more than 1 inline ref then it's shared */
-       if (item_size != sizeof(*ei) +
-           btrfs_extent_inline_ref_size(BTRFS_EXTENT_DATA_REF_KEY))
+       if (item_size != expected_size)
                goto out;
 
        /*
@@ -2352,8 +2411,6 @@ static noinline int check_committed_ref(struct btrfs_root *root,
             btrfs_root_last_snapshot(&root->root_item)))
                goto out;
 
-       iref = (struct btrfs_extent_inline_ref *)(ei + 1);
-
        /* If this extent has SHARED_DATA_REF then it's shared */
        type = btrfs_get_extent_inline_ref_type(leaf, iref, BTRFS_REF_TYPE_DATA);
        if (type != BTRFS_EXTENT_DATA_REF_KEY)
@@ -2450,7 +2507,7 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans,
                        num_bytes = btrfs_file_extent_disk_num_bytes(buf, fi);
                        key.offset -= btrfs_file_extent_offset(buf, fi);
                        btrfs_init_generic_ref(&generic_ref, action, bytenr,
-                                              num_bytes, parent);
+                                              num_bytes, parent, ref_root);
                        btrfs_init_data_ref(&generic_ref, ref_root, key.objectid,
                                            key.offset, root->root_key.objectid,
                                            for_reloc);
@@ -2463,8 +2520,9 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans,
                } else {
                        bytenr = btrfs_node_blockptr(buf, i);
                        num_bytes = fs_info->nodesize;
+                       /* We don't know the owning_root, use 0. */
                        btrfs_init_generic_ref(&generic_ref, action, bytenr,
-                                              num_bytes, parent);
+                                              num_bytes, parent, 0);
                        btrfs_init_tree_ref(&generic_ref, level - 1, ref_root,
                                            root->root_key.objectid, for_reloc);
                        if (inc)
@@ -2565,16 +2623,13 @@ int btrfs_pin_extent(struct btrfs_trans_handle *trans,
        return 0;
 }
 
-/*
- * this function must be called within transaction
- */
 int btrfs_pin_extent_for_log_replay(struct btrfs_trans_handle *trans,
-                                   u64 bytenr, u64 num_bytes)
+                                   const struct extent_buffer *eb)
 {
        struct btrfs_block_group *cache;
        int ret;
 
-       cache = btrfs_lookup_block_group(trans->fs_info, bytenr);
+       cache = btrfs_lookup_block_group(trans->fs_info, eb->start);
        if (!cache)
                return -EINVAL;
 
@@ -2586,10 +2641,10 @@ int btrfs_pin_extent_for_log_replay(struct btrfs_trans_handle *trans,
        if (ret)
                goto out;
 
-       pin_down_extent(trans, cache, bytenr, num_bytes, 0);
+       pin_down_extent(trans, cache, eb->start, eb->len, 0);
 
        /* remove us from the free space cache (if we're there at all) */
-       ret = btrfs_remove_free_space(cache, bytenr, num_bytes);
+       ret = btrfs_remove_free_space(cache, eb->start, eb->len);
 out:
        btrfs_put_block_group(cache);
        return ret;
@@ -2844,12 +2899,61 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans)
        return 0;
 }
 
+/*
+ * Parse an extent item's inline extents looking for a simple quotas owner ref.
+ *
+ * @fs_info:   the btrfs_fs_info for this mount
+ * @leaf:      a leaf in the extent tree containing the extent item
+ * @slot:      the slot in the leaf where the extent item is found
+ *
+ * Returns the objectid of the root that originally allocated the extent item
+ * if the inline owner ref is expected and present, otherwise 0.
+ *
+ * If an extent item has an owner ref item, it will be the first inline ref
+ * item. Therefore the logic is to check whether there are any inline ref
+ * items, then check the type of the first one.
+ */
+u64 btrfs_get_extent_owner_root(struct btrfs_fs_info *fs_info,
+                               struct extent_buffer *leaf, int slot)
+{
+       struct btrfs_extent_item *ei;
+       struct btrfs_extent_inline_ref *iref;
+       struct btrfs_extent_owner_ref *oref;
+       unsigned long ptr;
+       unsigned long end;
+       int type;
+
+       if (!btrfs_fs_incompat(fs_info, SIMPLE_QUOTA))
+               return 0;
+
+       ei = btrfs_item_ptr(leaf, slot, struct btrfs_extent_item);
+       ptr = (unsigned long)(ei + 1);
+       end = (unsigned long)ei + btrfs_item_size(leaf, slot);
+
+       /* No inline ref items of any kind, can't check type. */
+       if (ptr == end)
+               return 0;
+
+       iref = (struct btrfs_extent_inline_ref *)ptr;
+       type = btrfs_get_extent_inline_ref_type(leaf, iref, BTRFS_REF_TYPE_ANY);
+
+       /* We found an owner ref, get the root out of it. */
+       if (type == BTRFS_EXTENT_OWNER_REF_KEY) {
+               oref = (struct btrfs_extent_owner_ref *)(&iref->offset);
+               return btrfs_extent_owner_ref_root_id(leaf, oref);
+       }
+
+       /* We have inline refs, but not an owner ref. */
+       return 0;
+}
+
 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);
@@ -2858,6 +2962,18 @@ static int do_free_extent_accounting(struct btrfs_trans_handle *trans,
                        btrfs_abort_transaction(trans, ret);
                        return ret;
                }
+
+               ret = btrfs_delete_raid_extent(trans, bytenr, num_bytes);
+               if (ret) {
+                       btrfs_abort_transaction(trans, ret);
+                       return ret;
+               }
+       }
+
+       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);
@@ -2940,9 +3056,10 @@ static int do_free_extent_accounting(struct btrfs_trans_handle *trans,
  * 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, int refs_to_drop,
+                              u64 owner_offset,
                               struct btrfs_delayed_extent_op *extent_op)
 {
        struct btrfs_fs_info *info = trans->fs_info;
@@ -2957,11 +3074,13 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
        int extent_slot = 0;
        int found_extent = 0;
        int num_to_del = 1;
+       int refs_to_drop = node->ref_mod;
        u32 item_size;
        u64 refs;
        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);
@@ -3151,7 +3270,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
                        }
                } else {
                        btrfs_set_extent_refs(leaf, ei, refs);
-                       btrfs_mark_buffer_dirty(leaf);
+                       btrfs_mark_buffer_dirty(trans, leaf);
                }
                if (found_extent) {
                        ret = remove_extent_backref(trans, extent_root, path,
@@ -3162,6 +3281,14 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
                        }
                }
        } 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 !=
@@ -3200,6 +3327,16 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
                                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);
@@ -3209,7 +3346,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
                }
                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);
 
@@ -3283,7 +3420,7 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
        int ret;
 
        btrfs_init_generic_ref(&generic_ref, BTRFS_DROP_DELAYED_REF,
-                              buf->start, buf->len, parent);
+                              buf->start, buf->len, parent, btrfs_header_owner(buf));
        btrfs_init_tree_ref(&generic_ref, btrfs_header_level(buf),
                            root_id, 0, false);
 
@@ -3370,10 +3507,9 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_ref *ref)
         * tree, just update pinning info and exit early.
         */
        if ((ref->type == BTRFS_REF_METADATA &&
-            ref->tree_ref.owning_root == BTRFS_TREE_LOG_OBJECTID) ||
+            ref->tree_ref.ref_root == BTRFS_TREE_LOG_OBJECTID) ||
            (ref->type == BTRFS_REF_DATA &&
-            ref->data_ref.owning_root == BTRFS_TREE_LOG_OBJECTID)) {
-               /* unlocks the pinned mutex */
+            ref->data_ref.ref_root == BTRFS_TREE_LOG_OBJECTID)) {
                btrfs_pin_extent(trans, ref->bytenr, ref->len, 1);
                ret = 0;
        } else if (ref->type == BTRFS_REF_METADATA) {
@@ -3383,9 +3519,9 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_ref *ref)
        }
 
        if (!((ref->type == BTRFS_REF_METADATA &&
-              ref->tree_ref.owning_root == BTRFS_TREE_LOG_OBJECTID) ||
+              ref->tree_ref.ref_root == BTRFS_TREE_LOG_OBJECTID) ||
              (ref->type == BTRFS_REF_DATA &&
-              ref->data_ref.owning_root == BTRFS_TREE_LOG_OBJECTID)))
+              ref->data_ref.ref_root == BTRFS_TREE_LOG_OBJECTID)))
                btrfs_ref_tree_mod(fs_info, ref);
 
        return ret;
@@ -4442,8 +4578,8 @@ loop:
 }
 
 /*
- * btrfs_reserve_extent - entry point to the extent allocator. Tries to find a
- *                       hole that is at least as big as @num_bytes.
+ * Entry point to the extent allocator. Tries to find a hole that is at least
+ * as big as @num_bytes.
  *
  * @root           -   The root that will contain this extent
  *
@@ -4562,20 +4698,20 @@ int btrfs_free_reserved_extent(struct btrfs_fs_info *fs_info,
        return 0;
 }
 
-int btrfs_pin_reserved_extent(struct btrfs_trans_handle *trans, u64 start,
-                             u64 len)
+int btrfs_pin_reserved_extent(struct btrfs_trans_handle *trans,
+                             const struct extent_buffer *eb)
 {
        struct btrfs_block_group *cache;
        int ret = 0;
 
-       cache = btrfs_lookup_block_group(trans->fs_info, start);
+       cache = btrfs_lookup_block_group(trans->fs_info, eb->start);
        if (!cache) {
                btrfs_err(trans->fs_info, "unable to find block group for %llu",
-                         start);
+                         eb->start);
                return -ENOSPC;
        }
 
-       ret = pin_down_extent(trans, cache, start, len, 1);
+       ret = pin_down_extent(trans, cache, eb->start, eb->len, 1);
        btrfs_put_block_group(cache);
        return ret;
 }
@@ -4611,18 +4747,23 @@ static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
        struct btrfs_root *extent_root;
        int ret;
        struct btrfs_extent_item *extent_item;
+       struct btrfs_extent_owner_ref *oref;
        struct btrfs_extent_inline_ref *iref;
        struct btrfs_path *path;
        struct extent_buffer *leaf;
        int type;
        u32 size;
+       const bool simple_quota = (btrfs_qgroup_mode(fs_info) == BTRFS_QGROUP_MODE_SIMPLE);
 
        if (parent > 0)
                type = BTRFS_SHARED_DATA_REF_KEY;
        else
                type = BTRFS_EXTENT_DATA_REF_KEY;
 
-       size = sizeof(*extent_item) + btrfs_extent_inline_ref_size(type);
+       size = sizeof(*extent_item);
+       if (simple_quota)
+               size += btrfs_extent_inline_ref_size(BTRFS_EXTENT_OWNER_REF_KEY);
+       size += btrfs_extent_inline_ref_size(type);
 
        path = btrfs_alloc_path();
        if (!path)
@@ -4644,7 +4785,14 @@ static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
                               flags | BTRFS_EXTENT_FLAG_DATA);
 
        iref = (struct btrfs_extent_inline_ref *)(extent_item + 1);
+       if (simple_quota) {
+               btrfs_set_extent_inline_ref_type(leaf, iref, BTRFS_EXTENT_OWNER_REF_KEY);
+               oref = (struct btrfs_extent_owner_ref *)(&iref->offset);
+               btrfs_set_extent_owner_ref_root_id(leaf, oref, root_objectid);
+               iref = (struct btrfs_extent_inline_ref *)(oref + 1);
+       }
        btrfs_set_extent_inline_ref_type(leaf, iref, type);
+
        if (parent > 0) {
                struct btrfs_shared_data_ref *ref;
                ref = (struct btrfs_shared_data_ref *)(iref + 1);
@@ -4659,7 +4807,7 @@ static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
                btrfs_set_extent_data_ref_count(leaf, ref, ref_mod);
        }
 
-       btrfs_mark_buffer_dirty(path->nodes[0]);
+       btrfs_mark_buffer_dirty(trans, path->nodes[0]);
        btrfs_free_path(path);
 
        return alloc_reserved_extent(trans, ins->objectid, ins->offset);
@@ -4734,7 +4882,7 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
                btrfs_set_extent_inline_ref_offset(leaf, iref, ref->root);
        }
 
-       btrfs_mark_buffer_dirty(leaf);
+       btrfs_mark_buffer_dirty(trans, leaf);
        btrfs_free_path(path);
 
        return alloc_reserved_extent(trans, node->bytenr, fs_info->nodesize);
@@ -4746,12 +4894,14 @@ int btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
                                     struct btrfs_key *ins)
 {
        struct btrfs_ref generic_ref = { 0 };
+       u64 root_objectid = root->root_key.objectid;
+       u64 owning_root = root_objectid;
 
-       BUG_ON(root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID);
+       BUG_ON(root_objectid == BTRFS_TREE_LOG_OBJECTID);
 
        btrfs_init_generic_ref(&generic_ref, BTRFS_ADD_DELAYED_EXTENT,
-                              ins->objectid, ins->offset, 0);
-       btrfs_init_data_ref(&generic_ref, root->root_key.objectid, owner,
+                              ins->objectid, ins->offset, 0, owning_root);
+       btrfs_init_data_ref(&generic_ref, root_objectid, owner,
                            offset, 0, false);
        btrfs_ref_tree_mod(root->fs_info, &generic_ref);
 
@@ -4771,6 +4921,13 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans,
        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
@@ -4799,10 +4956,33 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans,
                                         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;
 }
 
+#ifdef CONFIG_BTRFS_DEBUG
+/*
+ * Extra safety check in case the extent tree is corrupted and extent allocator
+ * chooses to use a tree block which is already used and locked.
+ */
+static bool check_eb_lock_owner(const struct extent_buffer *eb)
+{
+       if (eb->lock_owner == current->pid) {
+               btrfs_err_rl(eb->fs_info,
+"tree block %llu owner %llu already locked by pid=%d, extent tree corruption detected",
+                            eb->start, btrfs_header_owner(eb), current->pid);
+               return true;
+       }
+       return false;
+}
+#else
+static bool check_eb_lock_owner(struct extent_buffer *eb)
+{
+       return false;
+}
+#endif
+
 static struct extent_buffer *
 btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root,
                      u64 bytenr, int level, u64 owner,
@@ -4816,15 +4996,7 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root,
        if (IS_ERR(buf))
                return buf;
 
-       /*
-        * Extra safety check in case the extent tree is corrupted and extent
-        * allocator chooses to use a tree block which is already used and
-        * locked.
-        */
-       if (buf->lock_owner == current->pid) {
-               btrfs_err_rl(fs_info,
-"tree block %llu owner %llu already locked by pid=%d, extent tree corruption detected",
-                       buf->start, btrfs_header_owner(buf), current->pid);
+       if (check_eb_lock_owner(buf)) {
                free_extent_buffer(buf);
                return ERR_PTR(-EUCLEAN);
        }
@@ -4963,7 +5135,8 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
                extent_op->level = level;
 
                btrfs_init_generic_ref(&generic_ref, BTRFS_ADD_DELAYED_EXTENT,
-                                      ins.objectid, ins.offset, parent);
+                                      ins.objectid, ins.offset, parent,
+                                      btrfs_header_owner(buf));
                btrfs_init_tree_ref(&generic_ref, level, root_objectid,
                                    root->root_key.objectid, false);
                btrfs_ref_tree_mod(fs_info, &generic_ref);
@@ -5384,7 +5557,8 @@ skip:
                find_next_key(path, level, &wc->drop_progress);
 
                btrfs_init_generic_ref(&ref, BTRFS_DROP_DELAYED_REF, bytenr,
-                                      fs_info->nodesize, parent);
+                                      fs_info->nodesize, parent,
+                                      btrfs_header_owner(next));
                btrfs_init_tree_ref(&ref, level - 1, root->root_key.objectid,
                                    0, false);
                ret = btrfs_free_extent(trans, &ref);