]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - fs/btrfs/qgroup.c
btrfs: pull node/sector/stripe sizes out of root and into fs_info
[mirror_ubuntu-artful-kernel.git] / fs / btrfs / qgroup.c
index 8db2e29fdcf417db6096a107c938a4a133fb6af2..1fd9bef8cf3bce9da51a91b559bae47120538b40 100644 (file)
@@ -131,8 +131,15 @@ struct btrfs_qgroup_list {
        struct btrfs_qgroup *member;
 };
 
-#define ptr_to_u64(x) ((u64)(uintptr_t)x)
-#define u64_to_ptr(x) ((struct btrfs_qgroup *)(uintptr_t)x)
+static inline u64 qgroup_to_aux(struct btrfs_qgroup *qg)
+{
+       return (u64)(uintptr_t)qg;
+}
+
+static inline struct btrfs_qgroup* unode_aux_to_qgroup(struct ulist_node *n)
+{
+       return (struct btrfs_qgroup *)(uintptr_t)n->aux;
+}
 
 static int
 qgroup_rescan_init(struct btrfs_fs_info *fs_info, u64 progress_objectid,
@@ -309,7 +316,7 @@ int btrfs_read_qgroup_config(struct btrfs_fs_info *fs_info)
        u64 flags = 0;
        u64 rescan_progress = 0;
 
-       if (!fs_info->quota_enabled)
+       if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
                return 0;
 
        fs_info->qgroup_ulist = ulist_alloc(GFP_NOFS);
@@ -360,8 +367,7 @@ int btrfs_read_qgroup_config(struct btrfs_fs_info *fs_info)
                            fs_info->generation) {
                                flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
                                btrfs_err(fs_info,
-                                       "qgroup generation mismatch, "
-                                       "marked as inconsistent");
+                                       "qgroup generation mismatch, marked as inconsistent");
                        }
                        fs_info->qgroup_flags = btrfs_qgroup_status_flags(l,
                                                                          ptr);
@@ -463,13 +469,11 @@ next2:
        }
 out:
        fs_info->qgroup_flags |= flags;
-       if (!(fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_ON)) {
-               fs_info->quota_enabled = 0;
-               fs_info->pending_quota_state = 0;
-       } else if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN &&
-                  ret >= 0) {
+       if (!(fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_ON))
+               clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
+       else if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN &&
+                ret >= 0)
                ret = qgroup_rescan_init(fs_info, rescan_progress, 0);
-       }
        btrfs_free_path(path);
 
        if (ret < 0) {
@@ -847,7 +851,7 @@ static int btrfs_clean_quota_tree(struct btrfs_trans_handle *trans,
        }
        ret = 0;
 out:
-       root->fs_info->pending_quota_state = 0;
+       set_bit(BTRFS_FS_QUOTA_DISABLING, &root->fs_info->flags);
        btrfs_free_path(path);
        return ret;
 }
@@ -868,7 +872,7 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans,
 
        mutex_lock(&fs_info->qgroup_ioctl_lock);
        if (fs_info->quota_root) {
-               fs_info->pending_quota_state = 1;
+               set_bit(BTRFS_FS_QUOTA_ENABLING, &fs_info->flags);
                goto out;
        }
 
@@ -964,7 +968,7 @@ out_add_root:
        }
        spin_lock(&fs_info->qgroup_lock);
        fs_info->quota_root = quota_root;
-       fs_info->pending_quota_state = 1;
+       set_bit(BTRFS_FS_QUOTA_ENABLING, &fs_info->flags);
        spin_unlock(&fs_info->qgroup_lock);
 out_free_path:
        btrfs_free_path(path);
@@ -993,8 +997,8 @@ int btrfs_quota_disable(struct btrfs_trans_handle *trans,
        mutex_lock(&fs_info->qgroup_ioctl_lock);
        if (!fs_info->quota_root)
                goto out;
-       fs_info->quota_enabled = 0;
-       fs_info->pending_quota_state = 0;
+       clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
+       set_bit(BTRFS_FS_QUOTA_DISABLING, &fs_info->flags);
        btrfs_qgroup_wait_for_completion(fs_info, false);
        spin_lock(&fs_info->qgroup_lock);
        quota_root = fs_info->quota_root;
@@ -1069,7 +1073,7 @@ static int __qgroup_excl_accounting(struct btrfs_fs_info *fs_info,
        /* Get all of the parent groups that contain this qgroup */
        list_for_each_entry(glist, &qgroup->groups, next_group) {
                ret = ulist_add(tmp, glist->group->qgroupid,
-                               ptr_to_u64(glist->group), GFP_ATOMIC);
+                               qgroup_to_aux(glist->group), GFP_ATOMIC);
                if (ret < 0)
                        goto out;
        }
@@ -1077,7 +1081,7 @@ static int __qgroup_excl_accounting(struct btrfs_fs_info *fs_info,
        /* Iterate all of the parents and adjust their reference counts */
        ULIST_ITER_INIT(&uiter);
        while ((unode = ulist_next(tmp, &uiter))) {
-               qgroup = u64_to_ptr(unode->aux);
+               qgroup = unode_aux_to_qgroup(unode);
                qgroup->rfer += sign * num_bytes;
                qgroup->rfer_cmpr += sign * num_bytes;
                WARN_ON(sign < 0 && qgroup->excl < num_bytes);
@@ -1090,7 +1094,7 @@ static int __qgroup_excl_accounting(struct btrfs_fs_info *fs_info,
                /* Add any parents of the parents */
                list_for_each_entry(glist, &qgroup->groups, next_group) {
                        ret = ulist_add(tmp, glist->group->qgroupid,
-                                       ptr_to_u64(glist->group), GFP_ATOMIC);
+                                       qgroup_to_aux(glist->group), GFP_ATOMIC);
                        if (ret < 0)
                                goto out;
                }
@@ -1453,7 +1457,7 @@ int btrfs_qgroup_prepare_account_extents(struct btrfs_trans_handle *trans,
        return ret;
 }
 
-int btrfs_qgroup_insert_dirty_extent_nolock(struct btrfs_fs_info *fs_info,
+int btrfs_qgroup_trace_extent_nolock(struct btrfs_fs_info *fs_info,
                                struct btrfs_delayed_ref_root *delayed_refs,
                                struct btrfs_qgroup_extent_record *record)
 {
@@ -1463,7 +1467,7 @@ int btrfs_qgroup_insert_dirty_extent_nolock(struct btrfs_fs_info *fs_info,
        u64 bytenr = record->bytenr;
 
        assert_spin_locked(&delayed_refs->lock);
-       trace_btrfs_qgroup_insert_dirty_extent(fs_info, record);
+       trace_btrfs_qgroup_trace_extent(fs_info, record);
 
        while (*p) {
                parent_node = *p;
@@ -1482,7 +1486,7 @@ int btrfs_qgroup_insert_dirty_extent_nolock(struct btrfs_fs_info *fs_info,
        return 0;
 }
 
-int btrfs_qgroup_insert_dirty_extent(struct btrfs_trans_handle *trans,
+int btrfs_qgroup_trace_extent(struct btrfs_trans_handle *trans,
                struct btrfs_fs_info *fs_info, u64 bytenr, u64 num_bytes,
                gfp_t gfp_flag)
 {
@@ -1490,7 +1494,8 @@ int btrfs_qgroup_insert_dirty_extent(struct btrfs_trans_handle *trans,
        struct btrfs_delayed_ref_root *delayed_refs;
        int ret;
 
-       if (!fs_info->quota_enabled || bytenr == 0 || num_bytes == 0)
+       if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)
+           || bytenr == 0 || num_bytes == 0)
                return 0;
        if (WARN_ON(trans == NULL))
                return -EINVAL;
@@ -1504,7 +1509,7 @@ int btrfs_qgroup_insert_dirty_extent(struct btrfs_trans_handle *trans,
        record->old_roots = NULL;
 
        spin_lock(&delayed_refs->lock);
-       ret = btrfs_qgroup_insert_dirty_extent_nolock(fs_info, delayed_refs,
+       ret = btrfs_qgroup_trace_extent_nolock(fs_info, delayed_refs,
                                                      record);
        spin_unlock(&delayed_refs->lock);
        if (ret > 0)
@@ -1512,6 +1517,219 @@ int btrfs_qgroup_insert_dirty_extent(struct btrfs_trans_handle *trans,
        return 0;
 }
 
+int btrfs_qgroup_trace_leaf_items(struct btrfs_trans_handle *trans,
+                                 struct btrfs_root *root,
+                                 struct extent_buffer *eb)
+{
+       int nr = btrfs_header_nritems(eb);
+       int i, extent_type, ret;
+       struct btrfs_key key;
+       struct btrfs_file_extent_item *fi;
+       u64 bytenr, num_bytes;
+
+       /* We can be called directly from walk_up_proc() */
+       if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags))
+               return 0;
+
+       for (i = 0; i < nr; i++) {
+               btrfs_item_key_to_cpu(eb, &key, i);
+
+               if (key.type != BTRFS_EXTENT_DATA_KEY)
+                       continue;
+
+               fi = btrfs_item_ptr(eb, i, struct btrfs_file_extent_item);
+               /* filter out non qgroup-accountable extents  */
+               extent_type = btrfs_file_extent_type(eb, fi);
+
+               if (extent_type == BTRFS_FILE_EXTENT_INLINE)
+                       continue;
+
+               bytenr = btrfs_file_extent_disk_bytenr(eb, fi);
+               if (!bytenr)
+                       continue;
+
+               num_bytes = btrfs_file_extent_disk_num_bytes(eb, fi);
+
+               ret = btrfs_qgroup_trace_extent(trans, root->fs_info,
+                                               bytenr, num_bytes, GFP_NOFS);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+
+/*
+ * Walk up the tree from the bottom, freeing leaves and any interior
+ * nodes which have had all slots visited. If a node (leaf or
+ * interior) is freed, the node above it will have it's slot
+ * incremented. The root node will never be freed.
+ *
+ * At the end of this function, we should have a path which has all
+ * slots incremented to the next position for a search. If we need to
+ * read a new node it will be NULL and the node above it will have the
+ * correct slot selected for a later read.
+ *
+ * If we increment the root nodes slot counter past the number of
+ * elements, 1 is returned to signal completion of the search.
+ */
+static int adjust_slots_upwards(struct btrfs_root *root,
+                               struct btrfs_path *path, int root_level)
+{
+       int level = 0;
+       int nr, slot;
+       struct extent_buffer *eb;
+
+       if (root_level == 0)
+               return 1;
+
+       while (level <= root_level) {
+               eb = path->nodes[level];
+               nr = btrfs_header_nritems(eb);
+               path->slots[level]++;
+               slot = path->slots[level];
+               if (slot >= nr || level == 0) {
+                       /*
+                        * Don't free the root -  we will detect this
+                        * condition after our loop and return a
+                        * positive value for caller to stop walking the tree.
+                        */
+                       if (level != root_level) {
+                               btrfs_tree_unlock_rw(eb, path->locks[level]);
+                               path->locks[level] = 0;
+
+                               free_extent_buffer(eb);
+                               path->nodes[level] = NULL;
+                               path->slots[level] = 0;
+                       }
+               } else {
+                       /*
+                        * We have a valid slot to walk back down
+                        * from. Stop here so caller can process these
+                        * new nodes.
+                        */
+                       break;
+               }
+
+               level++;
+       }
+
+       eb = path->nodes[root_level];
+       if (path->slots[root_level] >= btrfs_header_nritems(eb))
+               return 1;
+
+       return 0;
+}
+
+int btrfs_qgroup_trace_subtree(struct btrfs_trans_handle *trans,
+                              struct btrfs_root *root,
+                              struct extent_buffer *root_eb,
+                              u64 root_gen, int root_level)
+{
+       int ret = 0;
+       int level;
+       struct extent_buffer *eb = root_eb;
+       struct btrfs_path *path = NULL;
+
+       BUG_ON(root_level < 0 || root_level > BTRFS_MAX_LEVEL);
+       BUG_ON(root_eb == NULL);
+
+       if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags))
+               return 0;
+
+       if (!extent_buffer_uptodate(root_eb)) {
+               ret = btrfs_read_buffer(root_eb, root_gen);
+               if (ret)
+                       goto out;
+       }
+
+       if (root_level == 0) {
+               ret = btrfs_qgroup_trace_leaf_items(trans, root, root_eb);
+               goto out;
+       }
+
+       path = btrfs_alloc_path();
+       if (!path)
+               return -ENOMEM;
+
+       /*
+        * Walk down the tree.  Missing extent blocks are filled in as
+        * we go. Metadata is accounted every time we read a new
+        * extent block.
+        *
+        * When we reach a leaf, we account for file extent items in it,
+        * walk back up the tree (adjusting slot pointers as we go)
+        * and restart the search process.
+        */
+       extent_buffer_get(root_eb); /* For path */
+       path->nodes[root_level] = root_eb;
+       path->slots[root_level] = 0;
+       path->locks[root_level] = 0; /* so release_path doesn't try to unlock */
+walk_down:
+       level = root_level;
+       while (level >= 0) {
+               if (path->nodes[level] == NULL) {
+                       int parent_slot;
+                       u64 child_gen;
+                       u64 child_bytenr;
+
+                       /*
+                        * We need to get child blockptr/gen from parent before
+                        * we can read it.
+                         */
+                       eb = path->nodes[level + 1];
+                       parent_slot = path->slots[level + 1];
+                       child_bytenr = btrfs_node_blockptr(eb, parent_slot);
+                       child_gen = btrfs_node_ptr_generation(eb, parent_slot);
+
+                       eb = read_tree_block(root, child_bytenr, child_gen);
+                       if (IS_ERR(eb)) {
+                               ret = PTR_ERR(eb);
+                               goto out;
+                       } else if (!extent_buffer_uptodate(eb)) {
+                               free_extent_buffer(eb);
+                               ret = -EIO;
+                               goto out;
+                       }
+
+                       path->nodes[level] = eb;
+                       path->slots[level] = 0;
+
+                       btrfs_tree_read_lock(eb);
+                       btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
+                       path->locks[level] = BTRFS_READ_LOCK_BLOCKING;
+
+                       ret = btrfs_qgroup_trace_extent(trans,
+                                       root->fs_info, child_bytenr,
+                                       root->fs_info->nodesize, GFP_NOFS);
+                       if (ret)
+                               goto out;
+               }
+
+               if (level == 0) {
+                       ret = btrfs_qgroup_trace_leaf_items(trans, root,
+                                       path->nodes[level]);
+                       if (ret)
+                               goto out;
+
+                       /* Nonzero return here means we completed our search */
+                       ret = adjust_slots_upwards(root, path, root_level);
+                       if (ret)
+                               break;
+
+                       /* Restart search with new slots */
+                       goto walk_down;
+               }
+
+               level--;
+       }
+
+       ret = 0;
+out:
+       btrfs_free_path(path);
+
+       return ret;
+}
+
 #define UPDATE_NEW     0
 #define UPDATE_OLD     1
 /*
@@ -1537,30 +1755,30 @@ static int qgroup_update_refcnt(struct btrfs_fs_info *fs_info,
                        continue;
 
                ulist_reinit(tmp);
-               ret = ulist_add(qgroups, qg->qgroupid, ptr_to_u64(qg),
+               ret = ulist_add(qgroups, qg->qgroupid, qgroup_to_aux(qg),
                                GFP_ATOMIC);
                if (ret < 0)
                        return ret;
-               ret = ulist_add(tmp, qg->qgroupid, ptr_to_u64(qg), GFP_ATOMIC);
+               ret = ulist_add(tmp, qg->qgroupid, qgroup_to_aux(qg), GFP_ATOMIC);
                if (ret < 0)
                        return ret;
                ULIST_ITER_INIT(&tmp_uiter);
                while ((tmp_unode = ulist_next(tmp, &tmp_uiter))) {
                        struct btrfs_qgroup_list *glist;
 
-                       qg = u64_to_ptr(tmp_unode->aux);
+                       qg = unode_aux_to_qgroup(tmp_unode);
                        if (update_old)
                                btrfs_qgroup_update_old_refcnt(qg, seq, 1);
                        else
                                btrfs_qgroup_update_new_refcnt(qg, seq, 1);
                        list_for_each_entry(glist, &qg->groups, next_group) {
                                ret = ulist_add(qgroups, glist->group->qgroupid,
-                                               ptr_to_u64(glist->group),
+                                               qgroup_to_aux(glist->group),
                                                GFP_ATOMIC);
                                if (ret < 0)
                                        return ret;
                                ret = ulist_add(tmp, glist->group->qgroupid,
-                                               ptr_to_u64(glist->group),
+                                               qgroup_to_aux(glist->group),
                                                GFP_ATOMIC);
                                if (ret < 0)
                                        return ret;
@@ -1621,7 +1839,7 @@ static int qgroup_update_counters(struct btrfs_fs_info *fs_info,
        while ((unode = ulist_next(qgroups, &uiter))) {
                bool dirty = false;
 
-               qg = u64_to_ptr(unode->aux);
+               qg = unode_aux_to_qgroup(unode);
                cur_old_count = btrfs_qgroup_get_old_refcnt(qg, seq);
                cur_new_count = btrfs_qgroup_get_new_refcnt(qg, seq);
 
@@ -1713,7 +1931,7 @@ btrfs_qgroup_account_extent(struct btrfs_trans_handle *trans,
        if (old_roots)
                nr_old_roots = old_roots->nnodes;
 
-       if (!fs_info->quota_enabled)
+       if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
                goto out_free;
        BUG_ON(!fs_info->quota_root);
 
@@ -1833,10 +2051,14 @@ int btrfs_run_qgroups(struct btrfs_trans_handle *trans,
        if (!quota_root)
                goto out;
 
-       if (!fs_info->quota_enabled && fs_info->pending_quota_state)
+       if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags) &&
+           test_bit(BTRFS_FS_QUOTA_ENABLING, &fs_info->flags))
                start_rescan_worker = 1;
 
-       fs_info->quota_enabled = fs_info->pending_quota_state;
+       if (test_and_clear_bit(BTRFS_FS_QUOTA_ENABLING, &fs_info->flags))
+               set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
+       if (test_and_clear_bit(BTRFS_FS_QUOTA_DISABLING, &fs_info->flags))
+               clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
 
        spin_lock(&fs_info->qgroup_lock);
        while (!list_empty(&fs_info->dirty_qgroups)) {
@@ -1855,7 +2077,7 @@ int btrfs_run_qgroups(struct btrfs_trans_handle *trans,
                                        BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
                spin_lock(&fs_info->qgroup_lock);
        }
-       if (fs_info->quota_enabled)
+       if (test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
                fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_ON;
        else
                fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_ON;
@@ -1900,7 +2122,7 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
        u64 nums;
 
        mutex_lock(&fs_info->qgroup_ioctl_lock);
-       if (!fs_info->quota_enabled)
+       if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
                goto out;
 
        if (!quota_root) {
@@ -1948,7 +2170,7 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
                }
 
                rcu_read_lock();
-               level_size = srcroot->nodesize;
+               level_size = srcroot->fs_info->nodesize;
                rcu_read_unlock();
        }
 
@@ -1991,8 +2213,9 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
                ret = update_qgroup_limit_item(trans, quota_root, dstgroup);
                if (ret) {
                        fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
-                       btrfs_info(fs_info, "unable to update quota limit for %llu",
-                              dstgroup->qgroupid);
+                       btrfs_info(fs_info,
+                                  "unable to update quota limit for %llu",
+                                  dstgroup->qgroupid);
                        goto unlock;
                }
        }
@@ -2122,7 +2345,7 @@ static int qgroup_reserve(struct btrfs_root *root, u64 num_bytes)
                struct btrfs_qgroup *qg;
                struct btrfs_qgroup_list *glist;
 
-               qg = u64_to_ptr(unode->aux);
+               qg = unode_aux_to_qgroup(unode);
 
                if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_RFER) &&
                    qg->reserved + (s64)qg->rfer + num_bytes >
@@ -2154,7 +2377,7 @@ static int qgroup_reserve(struct btrfs_root *root, u64 num_bytes)
        while ((unode = ulist_next(fs_info->qgroup_ulist, &uiter))) {
                struct btrfs_qgroup *qg;
 
-               qg = u64_to_ptr(unode->aux);
+               qg = unode_aux_to_qgroup(unode);
 
                qg->reserved += num_bytes;
        }
@@ -2199,7 +2422,7 @@ void btrfs_qgroup_free_refroot(struct btrfs_fs_info *fs_info,
                struct btrfs_qgroup *qg;
                struct btrfs_qgroup_list *glist;
 
-               qg = u64_to_ptr(unode->aux);
+               qg = unode_aux_to_qgroup(unode);
 
                qg->reserved -= num_bytes;
 
@@ -2226,8 +2449,7 @@ void assert_qgroups_uptodate(struct btrfs_trans_handle *trans)
        if (list_empty(&trans->qgroup_ref_list) && !trans->delayed_ref_elem.seq)
                return;
        btrfs_err(trans->fs_info,
-               "qgroups not uptodate in trans handle %p:  list is%s empty, "
-               "seq is %#x.%x",
+               "qgroups not uptodate in trans handle %p:  list is%s empty, seq is %#x.%x",
                trans, list_empty(&trans->qgroup_ref_list) ? "" : " not",
                (u32)(trans->delayed_ref_elem.seq >> 32),
                (u32)trans->delayed_ref_elem.seq);
@@ -2255,10 +2477,11 @@ qgroup_rescan_leaf(struct btrfs_fs_info *fs_info, struct btrfs_path *path,
                                         &fs_info->qgroup_rescan_progress,
                                         path, 1, 0);
 
-       pr_debug("current progress key (%llu %u %llu), search_slot ret %d\n",
-                fs_info->qgroup_rescan_progress.objectid,
-                fs_info->qgroup_rescan_progress.type,
-                fs_info->qgroup_rescan_progress.offset, ret);
+       btrfs_debug(fs_info,
+               "current progress key (%llu %u %llu), search_slot ret %d",
+               fs_info->qgroup_rescan_progress.objectid,
+               fs_info->qgroup_rescan_progress.type,
+               fs_info->qgroup_rescan_progress.offset, ret);
 
        if (ret) {
                /*
@@ -2299,7 +2522,7 @@ qgroup_rescan_leaf(struct btrfs_fs_info *fs_info, struct btrfs_path *path,
                    found.type != BTRFS_METADATA_ITEM_KEY)
                        continue;
                if (found.type == BTRFS_METADATA_ITEM_KEY)
-                       num_bytes = fs_info->extent_root->nodesize;
+                       num_bytes = fs_info->nodesize;
                else
                        num_bytes = found.offset;
 
@@ -2347,7 +2570,7 @@ static void btrfs_qgroup_rescan_worker(struct btrfs_work *work)
                        err = PTR_ERR(trans);
                        break;
                }
-               if (!fs_info->quota_enabled) {
+               if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) {
                        err = -EINTR;
                } else {
                        err = qgroup_rescan_leaf(fs_info, path, trans);
@@ -2388,7 +2611,7 @@ out:
        ret = update_qgroup_status_item(trans, fs_info, fs_info->quota_root);
        if (ret < 0) {
                err = ret;
-               btrfs_err(fs_info, "fail to update qgroup status: %d\n", err);
+               btrfs_err(fs_info, "fail to update qgroup status: %d", err);
        }
        btrfs_end_transaction(trans, fs_info->quota_root);
 
@@ -2578,8 +2801,8 @@ int btrfs_qgroup_reserve_data(struct inode *inode, u64 start, u64 len)
        struct ulist_iterator uiter;
        int ret;
 
-       if (!root->fs_info->quota_enabled || !is_fstree(root->objectid) ||
-           len == 0)
+       if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags) ||
+           !is_fstree(root->objectid) || len == 0)
                return 0;
 
        changeset.bytes_changed = 0;
@@ -2676,11 +2899,11 @@ int btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes)
 {
        int ret;
 
-       if (!root->fs_info->quota_enabled || !is_fstree(root->objectid) ||
-           num_bytes == 0)
+       if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags) ||
+           !is_fstree(root->objectid) || num_bytes == 0)
                return 0;
 
-       BUG_ON(num_bytes != round_down(num_bytes, root->nodesize));
+       BUG_ON(num_bytes != round_down(num_bytes, root->fs_info->nodesize));
        ret = qgroup_reserve(root, num_bytes);
        if (ret < 0)
                return ret;
@@ -2692,7 +2915,8 @@ void btrfs_qgroup_free_meta_all(struct btrfs_root *root)
 {
        int reserved;
 
-       if (!root->fs_info->quota_enabled || !is_fstree(root->objectid))
+       if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags) ||
+           !is_fstree(root->objectid))
                return;
 
        reserved = atomic_xchg(&root->qgroup_meta_rsv, 0);
@@ -2703,10 +2927,11 @@ void btrfs_qgroup_free_meta_all(struct btrfs_root *root)
 
 void btrfs_qgroup_free_meta(struct btrfs_root *root, int num_bytes)
 {
-       if (!root->fs_info->quota_enabled || !is_fstree(root->objectid))
+       if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags) ||
+           !is_fstree(root->objectid))
                return;
 
-       BUG_ON(num_bytes != round_down(num_bytes, root->nodesize));
+       BUG_ON(num_bytes != round_down(num_bytes, root->fs_info->nodesize));
        WARN_ON(atomic_read(&root->qgroup_meta_rsv) < num_bytes);
        atomic_sub(num_bytes, &root->qgroup_meta_rsv);
        qgroup_free(root, num_bytes);