btrfs: waiting on qgroup rescan should not always be interruptible
[cascardo/linux.git] / fs / btrfs / qgroup.c
index 9e11955..13eb6a7 100644 (file)
@@ -85,7 +85,7 @@ struct btrfs_qgroup {
 
        /*
         * temp variables for accounting operations
-        * Refer to qgroup_shared_accouting() for details.
+        * Refer to qgroup_shared_accounting() for details.
         */
        u64 old_refcnt;
        u64 new_refcnt;
@@ -499,7 +499,7 @@ void btrfs_free_qgroup_config(struct btrfs_fs_info *fs_info)
        }
        /*
         * we call btrfs_free_qgroup_config() when umounting
-        * filesystem and disabling quota, so we set qgroup_ulit
+        * filesystem and disabling quota, so we set qgroup_ulist
         * to be null here to avoid double free.
         */
        ulist_free(fs_info->qgroup_ulist);
@@ -571,7 +571,7 @@ static int add_qgroup_item(struct btrfs_trans_handle *trans,
        struct extent_buffer *leaf;
        struct btrfs_key key;
 
-       if (btrfs_test_is_dummy_root(quota_root))
+       if (btrfs_is_testing(quota_root->fs_info))
                return 0;
 
        path = btrfs_alloc_path();
@@ -728,7 +728,7 @@ static int update_qgroup_info_item(struct btrfs_trans_handle *trans,
        int ret;
        int slot;
 
-       if (btrfs_test_is_dummy_root(root))
+       if (btrfs_is_testing(root->fs_info))
                return 0;
 
        key.objectid = 0;
@@ -995,7 +995,7 @@ int btrfs_quota_disable(struct btrfs_trans_handle *trans,
                goto out;
        fs_info->quota_enabled = 0;
        fs_info->pending_quota_state = 0;
-       btrfs_qgroup_wait_for_completion(fs_info);
+       btrfs_qgroup_wait_for_completion(fs_info, false);
        spin_lock(&fs_info->qgroup_lock);
        quota_root = fs_info->quota_root;
        fs_info->quota_root = NULL;
@@ -1036,7 +1036,7 @@ static void qgroup_dirty(struct btrfs_fs_info *fs_info,
 
 /*
  * The easy accounting, if we are adding/removing the only ref for an extent
- * then this qgroup and all of the parent qgroups get their refrence and
+ * then this qgroup and all of the parent qgroups get their reference and
  * exclusive counts adjusted.
  *
  * Caller should hold fs_info->qgroup_lock.
@@ -1436,7 +1436,7 @@ int btrfs_qgroup_prepare_account_extents(struct btrfs_trans_handle *trans,
 
        /*
         * No need to do lock, since this function will only be called in
-        * btrfs_commmit_transaction().
+        * btrfs_commit_transaction().
         */
        node = rb_first(&delayed_refs->dirty_extent_root);
        while (node) {
@@ -1453,9 +1453,10 @@ int btrfs_qgroup_prepare_account_extents(struct btrfs_trans_handle *trans,
        return ret;
 }
 
-struct btrfs_qgroup_extent_record
-*btrfs_qgroup_insert_dirty_extent(struct btrfs_delayed_ref_root *delayed_refs,
-                                 struct btrfs_qgroup_extent_record *record)
+struct btrfs_qgroup_extent_record *
+btrfs_qgroup_insert_dirty_extent(struct btrfs_fs_info *fs_info,
+                                struct btrfs_delayed_ref_root *delayed_refs,
+                                struct btrfs_qgroup_extent_record *record)
 {
        struct rb_node **p = &delayed_refs->dirty_extent_root.rb_node;
        struct rb_node *parent_node = NULL;
@@ -1463,7 +1464,7 @@ struct btrfs_qgroup_extent_record
        u64 bytenr = record->bytenr;
 
        assert_spin_locked(&delayed_refs->lock);
-       trace_btrfs_qgroup_insert_dirty_extent(record);
+       trace_btrfs_qgroup_insert_dirty_extent(fs_info, record);
 
        while (*p) {
                parent_node = *p;
@@ -1557,7 +1558,7 @@ static int qgroup_update_refcnt(struct btrfs_fs_info *fs_info,
  * A:  cur_old_roots < nr_old_roots    (not exclusive before)
  * !A: cur_old_roots == nr_old_roots   (possible exclusive before)
  * B:  cur_new_roots < nr_new_roots    (not exclusive now)
- * !B: cur_new_roots == nr_new_roots   (possible exclsuive now)
+ * !B: cur_new_roots == nr_new_roots   (possible exclusive now)
  *
  * Results:
  * +: Possible sharing -> exclusive    -: Possible exclusive -> sharing
@@ -1595,8 +1596,8 @@ static int qgroup_update_counters(struct btrfs_fs_info *fs_info,
                cur_old_count = btrfs_qgroup_get_old_refcnt(qg, seq);
                cur_new_count = btrfs_qgroup_get_new_refcnt(qg, seq);
 
-               trace_qgroup_update_counters(qg->qgroupid, cur_old_count,
-                                            cur_new_count);
+               trace_qgroup_update_counters(fs_info, qg->qgroupid,
+                                            cur_old_count, cur_new_count);
 
                /* Rfer update part */
                if (cur_old_count == 0 && cur_new_count > 0) {
@@ -1687,8 +1688,8 @@ btrfs_qgroup_account_extent(struct btrfs_trans_handle *trans,
                goto out_free;
        BUG_ON(!fs_info->quota_root);
 
-       trace_btrfs_qgroup_account_extent(bytenr, num_bytes, nr_old_roots,
-                                         nr_new_roots);
+       trace_btrfs_qgroup_account_extent(fs_info, bytenr, num_bytes,
+                                         nr_old_roots, nr_new_roots);
 
        qgroups = ulist_alloc(GFP_NOFS);
        if (!qgroups) {
@@ -1759,7 +1760,7 @@ int btrfs_qgroup_account_extents(struct btrfs_trans_handle *trans,
                record = rb_entry(node, struct btrfs_qgroup_extent_record,
                                  node);
 
-               trace_btrfs_qgroup_account_extents(record);
+               trace_btrfs_qgroup_account_extents(fs_info, record);
 
                if (!ret) {
                        /*
@@ -1851,7 +1852,7 @@ out:
 }
 
 /*
- * Copy the acounting information between qgroups. This is necessary
+ * Copy the accounting information between qgroups. This is necessary
  * when a snapshot or a subvolume is created. Throwing an error will
  * cause a transaction abort so we take extra care here to only error
  * when a readonly fs is a reasonable outcome.
@@ -2195,7 +2196,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->root->fs_info,
+       btrfs_err(trans->fs_info,
                "qgroups not uptodate in trans handle %p:  list is%s empty, "
                "seq is %#x.%x",
                trans, list_empty(&trans->qgroup_ref_list) ? "" : " not",
@@ -2302,6 +2303,10 @@ static void btrfs_qgroup_rescan_worker(struct btrfs_work *work)
        int err = -ENOMEM;
        int ret = 0;
 
+       mutex_lock(&fs_info->qgroup_rescan_lock);
+       fs_info->qgroup_rescan_running = true;
+       mutex_unlock(&fs_info->qgroup_rescan_lock);
+
        path = btrfs_alloc_path();
        if (!path)
                goto out;
@@ -2340,7 +2345,7 @@ out:
        mutex_unlock(&fs_info->qgroup_rescan_lock);
 
        /*
-        * only update status, since the previous part has alreay updated the
+        * only update status, since the previous part has already updated the
         * qgroup info.
         */
        trans = btrfs_start_transaction(fs_info->quota_root, 1);
@@ -2368,6 +2373,9 @@ out:
        }
 
 done:
+       mutex_lock(&fs_info->qgroup_rescan_lock);
+       fs_info->qgroup_rescan_running = false;
+       mutex_unlock(&fs_info->qgroup_rescan_lock);
        complete_all(&fs_info->qgroup_rescan_completion);
 }
 
@@ -2486,20 +2494,26 @@ btrfs_qgroup_rescan(struct btrfs_fs_info *fs_info)
        return 0;
 }
 
-int btrfs_qgroup_wait_for_completion(struct btrfs_fs_info *fs_info)
+int btrfs_qgroup_wait_for_completion(struct btrfs_fs_info *fs_info,
+                                    bool interruptible)
 {
        int running;
        int ret = 0;
 
        mutex_lock(&fs_info->qgroup_rescan_lock);
        spin_lock(&fs_info->qgroup_lock);
-       running = fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN;
+       running = fs_info->qgroup_rescan_running;
        spin_unlock(&fs_info->qgroup_lock);
        mutex_unlock(&fs_info->qgroup_rescan_lock);
 
-       if (running)
+       if (!running)
+               return 0;
+
+       if (interruptible)
                ret = wait_for_completion_interruptible(
                                        &fs_info->qgroup_rescan_completion);
+       else
+               wait_for_completion(&fs_info->qgroup_rescan_completion);
 
        return ret;
 }
@@ -2542,8 +2556,7 @@ int btrfs_qgroup_reserve_data(struct inode *inode, u64 start, u64 len)
        changeset.bytes_changed = 0;
        changeset.range_changed = ulist_alloc(GFP_NOFS);
        ret = set_record_extent_bits(&BTRFS_I(inode)->io_tree, start,
-                       start + len -1, EXTENT_QGROUP_RESERVED, GFP_NOFS,
-                       &changeset);
+                       start + len -1, EXTENT_QGROUP_RESERVED, &changeset);
        trace_btrfs_qgroup_reserve_data(inode, start, len,
                                        changeset.bytes_changed,
                                        QGROUP_RESERVE);
@@ -2580,8 +2593,7 @@ static int __btrfs_qgroup_release_data(struct inode *inode, u64 start, u64 len,
                return -ENOMEM;
 
        ret = clear_record_extent_bits(&BTRFS_I(inode)->io_tree, start, 
-                       start + len -1, EXTENT_QGROUP_RESERVED, GFP_NOFS,
-                       &changeset);
+                       start + len -1, EXTENT_QGROUP_RESERVED, &changeset);
        if (ret < 0)
                goto out;
 
@@ -2672,7 +2684,7 @@ void btrfs_qgroup_free_meta(struct btrfs_root *root, int num_bytes)
 }
 
 /*
- * Check qgroup reserved space leaking, normally at destory inode
+ * Check qgroup reserved space leaking, normally at destroy inode
  * time
  */
 void btrfs_qgroup_check_reserved_leak(struct inode *inode)
@@ -2688,7 +2700,7 @@ void btrfs_qgroup_check_reserved_leak(struct inode *inode)
                return;
 
        ret = clear_record_extent_bits(&BTRFS_I(inode)->io_tree, 0, (u64)-1,
-                       EXTENT_QGROUP_RESERVED, GFP_NOFS, &changeset);
+                       EXTENT_QGROUP_RESERVED, &changeset);
 
        WARN_ON(ret < 0);
        if (WARN_ON(changeset.bytes_changed)) {