}
 #endif
 
+static void qgroup_mark_inconsistent(struct btrfs_fs_info *fs_info)
+{
+       fs_info->qgroup_flags |= (BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT |
+                                 BTRFS_QGROUP_RUNTIME_FLAG_CANCEL_RESCAN);
+}
+
 /*
  * The full config is read in one go, only called from open_ctree()
  * It doesn't use any locking, as at this point we're still single-threaded
                        }
                        if (btrfs_qgroup_status_generation(l, ptr) !=
                            fs_info->generation) {
-                               flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
+                               qgroup_mark_inconsistent(fs_info);
                                btrfs_err(fs_info,
                                        "qgroup generation mismatch, marked as inconsistent");
                        }
                if ((qgroup && found_key.type == BTRFS_QGROUP_INFO_KEY) ||
                    (!qgroup && found_key.type == BTRFS_QGROUP_LIMIT_KEY)) {
                        btrfs_err(fs_info, "inconsistent qgroup config");
-                       flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
+                       qgroup_mark_inconsistent(fs_info);
                }
                if (!qgroup) {
                        qgroup = add_qgroup_rb(fs_info, found_key.offset);
 
        ret = update_qgroup_limit_item(trans, qgroup);
        if (ret) {
-               fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
+               qgroup_mark_inconsistent(fs_info);
                btrfs_info(fs_info, "unable to update quota limit for %llu",
                       qgroupid);
        }
        ret = btrfs_find_all_roots(NULL, trans->fs_info, bytenr, 0, &old_root,
                                   true);
        if (ret < 0) {
-               trans->fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
+               qgroup_mark_inconsistent(trans->fs_info);
                btrfs_warn(trans->fs_info,
 "error accounting new delayed refs extent (err code: %d), quota inconsistent",
                        ret);
 out:
        btrfs_free_path(dst_path);
        if (ret < 0)
-               fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
+               qgroup_mark_inconsistent(fs_info);
        return ret;
 }
 
                spin_unlock(&fs_info->qgroup_lock);
                ret = update_qgroup_info_item(trans, qgroup);
                if (ret)
-                       fs_info->qgroup_flags |=
-                                       BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
+                       qgroup_mark_inconsistent(fs_info);
                ret = update_qgroup_limit_item(trans, qgroup);
                if (ret)
-                       fs_info->qgroup_flags |=
-                                       BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
+                       qgroup_mark_inconsistent(fs_info);
                spin_lock(&fs_info->qgroup_lock);
        }
        if (test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
 
        ret = update_qgroup_status_item(trans);
        if (ret)
-               fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
+               qgroup_mark_inconsistent(fs_info);
 
        return ret;
 }
 
                ret = update_qgroup_limit_item(trans, dstgroup);
                if (ret) {
-                       fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
+                       qgroup_mark_inconsistent(fs_info);
                        btrfs_info(fs_info,
                                   "unable to update quota limit for %llu",
                                   dstgroup->qgroupid);
        if (!committing)
                mutex_unlock(&fs_info->qgroup_ioctl_lock);
        if (need_rescan)
-               fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
+               qgroup_mark_inconsistent(fs_info);
        return ret;
 }
 
 {
        return btrfs_fs_closing(fs_info) ||
                test_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state) ||
-               !test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
+               !test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags) ||
+                         fs_info->qgroup_flags & BTRFS_QGROUP_RUNTIME_FLAG_CANCEL_RESCAN;
 }
 
 static void btrfs_qgroup_rescan_worker(struct btrfs_work *work)
        }
 
        mutex_lock(&fs_info->qgroup_rescan_lock);
-       if (!stopped)
+       if (!stopped ||
+           fs_info->qgroup_flags & BTRFS_QGROUP_RUNTIME_FLAG_CANCEL_RESCAN)
                fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_RESCAN;
        if (trans) {
                ret = update_qgroup_status_item(trans);
                }
        }
        fs_info->qgroup_rescan_running = false;
+       fs_info->qgroup_flags &= ~BTRFS_QGROUP_RUNTIME_FLAG_CANCEL_RESCAN;
        complete_all(&fs_info->qgroup_rescan_completion);
        mutex_unlock(&fs_info->qgroup_rescan_lock);
 
 
        if (stopped) {
                btrfs_info(fs_info, "qgroup scan paused");
+       } else if (fs_info->qgroup_flags & BTRFS_QGROUP_RUNTIME_FLAG_CANCEL_RESCAN) {
+               btrfs_info(fs_info, "qgroup scan cancelled");
        } else if (err >= 0) {
                btrfs_info(fs_info, "qgroup scan completed%s",
                        err > 0 ? " (inconsistency flag cleared)" : "");
 
        memset(&fs_info->qgroup_rescan_progress, 0,
                sizeof(fs_info->qgroup_rescan_progress));
+       fs_info->qgroup_flags &= ~BTRFS_QGROUP_RUNTIME_FLAG_CANCEL_RESCAN;
        fs_info->qgroup_rescan_progress.objectid = progress_objectid;
        init_completion(&fs_info->qgroup_rescan_completion);
        mutex_unlock(&fs_info->qgroup_rescan_lock);
        spin_unlock(&blocks->lock);
 out:
        if (ret < 0)
-               fs_info->qgroup_flags |=
-                       BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
+               qgroup_mark_inconsistent(fs_info);
        return ret;
 }
 
                btrfs_err_rl(fs_info,
                             "failed to account subtree at bytenr %llu: %d",
                             subvol_eb->start, ret);
-               fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
+               qgroup_mark_inconsistent(fs_info);
        }
        return ret;
 }